I'm trying to implement a timeout that terminates a python script when no connections are receiving for a defined time interval. So far I manage to implement the timeout using the following code:
import sys
import socket
# Create a TCP/IP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Bind the socket to the port
server_address = ('192.168.43.112', 5001)
print >>sys.stderr, 'starting up on %s port %s' % server_address
sock.bind(server_address)
# Listen for incoming connections
sock.listen(1)
while True:
try:
# Wait for a connection
print >>sys.stderr, 'waiting for a connection'
connection, client_address = sock.accept()
try:
print >>sys.stderr, 'connection from', client_address
# Receive the data in small chunks and retransmit it
while True:
data = connection.recv(16)
print >>sys.stderr, 'received "%s"' % data
if data:
print >>sys.stderr, 'Do stuff here'
else:
print >>sys.stderr, 'no more data from', client_address
sock.settimeout(5)
break
finally:
# Clean up the connection
connection.close()
except socket.timeout:
break
The code is working correctly in the sense that after establishing a connection and ending that very same connection, after 5 seconds the script terminates. However, if during the timeout window I try to make another connection I have the following error:
starting up on 192.168.43.112 port 5001
waiting for a connection
connection from ('192.168.43.1', 47550)
received "Data 0
"
Do stuff here
received ""
no more data from ('192.168.43.1', 47550)
waiting for a connection
connection from ('192.168.43.1', 39010)
---------------------------------------------------------------------------
error Traceback (most recent call last)
/Users/location/Desktop/sandbox/data_fetcher.py in <module>()
24 # Receive the data in small chunks and retransmit it
25 while True:
---> 26 data = connection.recv(16)
27 print >>sys.stderr, 'received "%s"' % data
28 if data:
error: [Errno 35] Resource temporarily unavailable
I'm not entirely sure how you want this all to work, and I find it a bit surprising that it happens this way right now (I didn't expect the timeout to have this effect), but based on the EAGAIN error (errno 35), what's happening is that the timeout on the main socket—which gets set only once you've had a first connection—is causing the second -accepted socket to be in non-blocking mode as well. This means that when you call connection.recv
and there's no data immediately, you get that OSError
raised.
I suspect some of this might vary a bit between OSes, but I was able to reproduces this on FreeBSD (you're probably running on Linux).
A minimal change that works around it—I don't think this is necessarily the best way to code this, but it does work—is to explicitly set the accepted socket to blocking:
# Wait for a connection
print >>sys.stderr, 'waiting for a connection'
connection, client_address = sock.accept()
connection.setblocking(1)
With this, the code behaves much better (I added a small test framework that spins off your code as a separate process, then makes several connections with varying delays).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.