Py学习  »  Python

Python 3.8 TLSv1.3套接字关闭导致ConnectionResetError或ConnectionAbortedError

Myath • 5 年前 • 847 次点击  

客户端:

data = b'\xff' * 1000000
ssock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
#context is created by ssl.create_default_context(ssl.Purpose.SERVER_AUTH)
ssock = context.wrap_socket(ssock, server_hostname='xd1337sv')
ssock.connect((SERVERADDR, SERVERPORT))
ssock.sendall(data)
#time.sleep(3)
ssock.close()

如果我只是使用普通的非SSL套接字,那么在服务器接收到确切数量的数据时,一切正常。如果我使用TLS套接字,则行为取决于版本。

如果我在Python 3.6上运行服务器或客户端,因此将使用TLSv1.2,那么就没有问题。 仅当使用TLSv1.3并取决于 data 客户多久 ssocket.close() 行被执行。

如果我把适量的 time.sleep 之前 ssocket.close() 根据数据的大小,我不会出错。否则,服务器将获得 ConnectionResetError [WinError 10054] An existing connection was forcibly closed by the remote host 只接收部分数据,或者抛出 ConnectionAbortedError [WinError 10053] An established connection was aborted by the software in your host machine 没有收到任何数据。

我正在本地计算机上用本地地址测试服务器和客户端 192.168.1.2 .

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/51303
文章 [ 1 ]  |  最新文章 5 年前
Steffen Ullrich
Reply   •   1 楼
Steffen Ullrich    5 年前

这种差异是由TLS 1.3在TLS握手后发送会话票证造成的,而对于以前的TLS版本,会话票证是在TLS握手内发送的。因此,来自服务器的TLS 1.3数据(会话票证)将在 ssock.connect(...) 完成了。因为应用程序在 connect 当未读数据仍在底层TCP套接字的套接字缓冲区内时,它关闭套接字。这将导致RST发送到服务器,并在那里导致连接重置错误。

这是应用程序的已知问题,这些应用程序从不尝试从服务器读取数据。如果应用程序希望服务器响应并使用 recv 要获得它,这也会隐式地读取会话票证。

若要在不希望服务器返回任何应用程序数据时修复此情况,请在关闭套接字之前正确关闭套接字。由于这将读取服务器SSL shutdown消息,它还将隐式读取服务器之前发送的会话票证。

try:
    ssock = ssock.unwrap()
except:
    True
ssock.close()

有关更多信息,请参见 this issue this documentation .