Python `sock.recv()`在非阻塞套接字上的连接断开时返回空字符串

Python `sock.recv()`在非阻塞套接字上的连接断开时返回空字符串,python,python-2.7,sockets,Python,Python 2.7,Sockets,我在Python中有一个名为sock的非阻塞套接字。根据我的理解,如果对等方关闭了连接,recv()方法应该引发异常,但它返回一个空字符串('),我不知道为什么 这是我测试的脚本(来自): 如果对等方关闭连接,则此套接字应在recv()上引发socket.error,但它只返回' 我使用两个端子进行测试: # Terminal 1 ~$ nc -l -p9999 # Terminal 2 ~$ python ./test_script.py # Terminal 1 typingsomest

我在Python中有一个名为
sock
的非阻塞套接字。根据我的理解,如果对等方关闭了连接,
recv()
方法应该引发异常,但它返回一个空字符串(
'
),我不知道为什么

这是我测试的脚本(来自):

如果对等方关闭连接,则此套接字应在
recv()
上引发
socket.error
,但它只返回
'

我使用两个端子进行测试:

# Terminal 1
~$ nc -l -p9999

# Terminal 2
~$ python ./test_script.py

# Terminal 1
typingsomestring

# Terminal 2
No data available
No data available
No data available
got data 'typingsomestring
'
No data available
No data available

# Terminal 1
Ctrl+C # (killing nc)

# Terminal 2
got data ''
got data ''
got data ''
got data ''
got data ''
got data ''
got data ''
got data ''
got data ''
got data ''
got data ''
got data ''
got data ''
got data ''
got data ''
got data ''
got data ''
got data ''
got data ''

recv
在发生错误时引发异常。对等方关闭套接字不是错误,而是正常行为。事实上,这甚至不是一个完结:对等方只表示它将不再发送任何数据,但它仍可能接收数据。只有当双方都表示不再发送任何数据时,TCP连接才会关闭,即每一方都已发送FIN。

这是在底层操作系统
recv
系统调用中设计的:在对等方上关闭的套接字上读取,或在对等方使用
关闭(s,shutu-WR)后立即关闭
若要指示它将不再发送任何内容,请立即返回0字节的长度

这是成功读取0字节的唯一情况,因为当对等套接字保持打开时,成功读取会在阻塞套接字上返回至少一个字节,或者在非阻塞套接字上再次返回E_或E_WOULDBLOCK错误


TL/DR:观察到的行为没有异常

应用程序退出后套接字不会立即关闭。thx@ajpenster即使我等待关闭等待超时,它也会继续循环,但关闭等待并不意味着套接字已经关闭,只是等待关闭。试着杀死终端1,看看会发生什么。我不太清楚Python的语法,但在套接字上调用
Shutdown()
Close()
可能对您更有效
# Terminal 1
~$ nc -l -p9999

# Terminal 2
~$ python ./test_script.py

# Terminal 1
typingsomestring

# Terminal 2
No data available
No data available
No data available
got data 'typingsomestring
'
No data available
No data available

# Terminal 1
Ctrl+C # (killing nc)

# Terminal 2
got data ''
got data ''
got data ''
got data ''
got data ''
got data ''
got data ''
got data ''
got data ''
got data ''
got data ''
got data ''
got data ''
got data ''
got data ''
got data ''
got data ''
got data ''
got data ''