我在Python中有一个名为sock
的非阻塞套接字。根据我的理解,如果连接已被对等关闭,recv()
方法应引发异常,但它返回一个空字符串(''
),我不知道原因。
这是我测试的脚本(来自here):
import sys
import socket
import fcntl, os
import errno
from time import sleep
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('127.0.0.1',9999))
fcntl.fcntl(s, fcntl.F_SETFL, os.O_NONBLOCK)
while True:
try:
msg = s.recv(4096)
print("got data '{msg}'".format(msg=msg))
except socket.error, e:
err = e.args[0]
if err == errno.EAGAIN or err == errno.EWOULDBLOCK:
sleep(1)
print 'No data available'
continue
sys.exit(1)
如果对等方关闭连接,则此套接字应该在socket.error
上引发recv()
,而是仅返回''
。
我用这种方式测试,使用两个终端:
# 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 ''
答案 0 :(得分:2)
这是基础操作系统recv
系统调用中的按设计:对等体上关闭的套接字读取,或者对等体使用shutdown(s, SHUT_WR)
时表明它不会再发送任何东西,立即返回0字节的长度。
这是成功读取0字节的唯一情况,因为当对等套接字保持打开状态时,成功读取会在阻塞套接字上返回至少一个字节,或者在非阻塞套接字上返回E_AGAIN或E_WOULDBLOCK错误。
TL / DR:观察到的行为没有异常
答案 1 :(得分:0)
recv
会抛出异常。由对等方关闭套接字不是错误,但是是正常行为。实际上它甚至不是完全关闭:对等体仅表示它不会发送更多数据,但它可能仍然接收数据。 TCP连接仅在双方都表示不再发送数据时才会关闭,即每一方都发送了FIN。