What does Python's socket.recv() return for non-blocking sockets if no data is received until a timeout occurs?
In the case of a non blocking socket that has no data available, recv will throw the socket.error exception and the value of the exception will have the errno of either EAGAIN or EWOULDBLOCK. Example:
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)
except socket.error, e:
err = e.args[0]
if err == errno.EAGAIN or err == errno.EWOULDBLOCK:
sleep(1)
print 'No data available'
continue
else:
# a "real" error occurred
print e
sys.exit(1)
else:
# got a message, do something :)
The situation is a little different in the case where you've enabled non-blocking behavior via a time out with socket.settimeout(n)
or socket.setblocking(False)
. In this case a socket.error is stil raised, but in the case of a time out, the accompanying value of the exception is always a string set to 'timed out'. So, to handle this case you can do:
import sys
import socket
from time import sleep
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('127.0.0.1',9999))
s.settimeout(2)
while True:
try:
msg = s.recv(4096)
except socket.timeout, e:
err = e.args[0]
# this next if/else is a bit redundant, but illustrates how the
# timeout exception is setup
if err == 'timed out':
sleep(1)
print 'recv timed out, retry later'
continue
else:
print e
sys.exit(1)
except socket.error, e:
# Something else happened, handle error, exit, etc.
print e
sys.exit(1)
else:
if len(msg) == 0:
print 'orderly shutdown on server end'
sys.exit(0)
else:
# got a message do something :)
As indicated in the comments, this is also a more portable solution since it doesn't depend on OS specific functionality to put the socket into non-blockng mode.
See recv(2) and python socket for more details.
`sock.recv()` returns empty string when connection is dead on non-blocking socket
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.
Why won't Python's socket.recv() return -1
The recv_into
is just a wrapper of the C system call by name recv
. The return value of 0
is not an erroneous condition!
From Linux manuals, recv(2)
:
RETURN VALUE
These calls return the number of bytes received, or -1 if an error
occurred. In the event of an error, errno is set to indicate the
error.When a stream socket peer has performed an orderly shutdown,
the return value will be 0 (the traditional "end-of-file" return).Datagram sockets in various domains (e.g., the UNIX and Internet
domains) permit zero-length datagrams. When such a datagram is
received, the return value is 0.The value 0 may also be returned if the requested number of bytes
to receive from a stream socket was 0.
For error cases, Python will not return -1
, instead it will raise an appropriate exception.
For a stream sockets you must break the loop whenever recv_*
returns a value that indicates that 0 bytes were received. There is no point for checking -1
, but in case you do want to be extra certain, you can naturally use while sock.recv_into(....) > 0:
or similar.
The various read
calls in Python work in similar fashion.
Related Topics
Why Does Defining _Getitem_ on a Class Make It Iterable in Python
Download Image with Selenium Python
Python Extending with - Using Super() Python 3 VS Python 2
Number of Days Between 2 Dates, Excluding Weekends
How to Get System Timezone Setting and Pass It to Pytz.Timezone
What Is a '"Python"' Layer in Caffe
Not All Parameters Were Used in the SQL Statement (Python, MySQL)
Numpy.Unique with Order Preserved
How to Transpose Dataframe in Pandas Without Index
Should I Call Close() After Urllib.Urlopen()
How to Set Folder Permissions in Windows
What Does the Term "Broadcasting" Mean in Pandas Documentation
Asyncio.Sleep() VS Time.Sleep()
Python String 'Join' Is Faster () Than '+', But What's Wrong Here
Python Scope: "Unboundlocalerror: Local Variable 'C' Referenced Before Assignment"
Import Multiple Excel Files into Python Pandas and Concatenate Them into One Dataframe