sock.recv(1024), 当缓冲区没有数据时
如果是阻塞IO, 如果对面关闭, 返回empty, 否则会卡住
如果是非阻塞IO, 如果对面关闭,返回emtpy, 否则抛E_AGAIN 或 E_WOULDBLOCK error(参考文献[1]和[2])
以下是一个非阻塞IO的例子, 来自于一篇twisted教程的异步客户端代码:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(address)
sock.setblocking(0)
data = ''
while True:
try:
# 当远端的server端关闭时, 会返回空
# 第一次IO就绪确实能获取数据,但是while True多次(其实是第二次)直到没有数据时,就会抛出EWOULDBLOCK异常
new_data = sock.recv(1024)
except socket.error, e:
if e.args[0] == errno.EWOULDBLOCK:
print('每当读不到数据就跳过')
# this error code means we would have
# blocked if the socket was blocking.
# instead we skip to the next socket
break
raise
else:
if not new_data:
break
else:
print('len(new_data)=%d', len(new_data))
data += new_data
if not data: # sock.recv(1024)当server端关闭时, 会返回空
sockets.remove(sock)
sock.close()
print 'Task %d finished' % task_num
else:
addr_fmt = format_address(sock.getpeername())
msg = 'Task: got %d bytes of poetry from %s'
print msg % (len(data), addr_fmt)
关于阻塞IO何时返回的问题,文献[3]讲的非常清楚
From test, I concluded that in following three cases the socket.recv(recv_size) will return.
-
After the connection was closed. For example, the client side called socket.close() or any socket error occurred, it would return empty string.
-
Some data come, the size of data is more than recv_size.
-
Some data come, the size of data is less than recv_size and no more data come after a short time (I found 0.1s would work).
关于#3有如下的例子:
#server.py
while True:
data = sock.recv(10)
print data, 'EOF'
#client1.py
sock.sendall("12345")
sock.sendall("a" * 50)
#client2.py
sock.sendall("12345")
time.sleep(0.1)
sock.sendall("a" * 50)
When I run client1.py, the server.py echos:
12345aaaaa EOF
aaaaaaaaaa EOF
aaaaaaaaaa EOF
aaaaaaaaaa EOF
aaaaaaaaaa EOF
aaaaa EOF
When I run client2.py, the server.py echos:
12345 EOF
aaaaaaaaaa EOF
aaaaaaaaaa EOF
aaaaaaaaaa EOF
aaaaaaaaaa EOF
aaaaaaaaaa EOF
因为sock.recv(size)只要一收到数据后就会返回,而不是收到size长度后再返回,因此可以用下面的方法来读取size长度的数据(当然你应该确保确实有这么多数据):
def recv_blen(conn, blen):
b_data = conn.recv(blen)
while len(b_data) < blen:
b_data += conn.recv(blen)
return b_data
参考文献:
[1] https://stackoverflow.com/questions/37330993/sock-recv-returns-empty-string-when-connection-is-dead-on-non-blocking-socke
[2] https://stackoverflow.com/questions/20988640/python-tcp-socket-recv-returns-with-nothing-as-soon-as-connection-is-made
[3] https://stackoverflow.com/questions/7174927/when-does-socket-recvrecv-size-return
网友评论