Reputation: 3809
I have a non-blocking socket in Python called sock
. According to my understanding the recv()
method should raise an exception if the connection has been closed by the peer, but it returns an empty string (''
) and I don't know why.
This is the script I test with (from 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)
If the peer closes the connection this socket is supposed to raise socket.error
on recv()
, but instead it only returns ''
.
I test it this way, using two terminals:
# 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 ''
Upvotes: 8
Views: 14641
Reputation: 149065
This is by design in the underlying operating system recv
system call: a read on a socket closed on peer, or as soon as the peer used a shutdown(s, SHUT_WR)
to indicate it will no send anything more, returns immediately with a length of 0 bytes.
That is the only case when you have a successful read of 0 bytes, because while the peer socket remains open, a successful read returns at least one byte on a blocking socket or a E_AGAIN or E_WOULDBLOCK error on a non blocking socket.
TL/DR: there is no anomaly in observed behaviour
Upvotes: 9
Reputation: 123423
recv
throws an exception if an error occurred. Closing a socket by the peer is no error, but is a normal behavior. In fact it is not even a full close: the peer only indicates that it will not send any more data, but it might still receive data. The TCP connection is only closed if both sides indicate that they will not send any more data, i.e. each side has send the FIN.
Upvotes: 2