In the case of a non-blocking socket that has no data available, recv will throw a socket.error exception, and the exception value will have errno 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:
The situation is a bit different when you socket.settimeout(n) non-blocking behavior through a timeout with socket.settimeout(n) or socket.setblocking(False) . In this case, socket.error is raised, but in the case of a timeout, the accompanying exception value is always a string set to "timeout". So, to handle this case, you can:
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 stated in the comments, this is also a more portable solution, since it does not depend on specific OS functions in order to put the socket in non-blocking mode.
See recv (2) and python socket for more details.
mshildt May 25 '13 at 1:26 2013-05-25 01:26
source share