1

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
asked Nov 5, 2015 at 16:33

1 Answer 1

1

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).

answered Nov 5, 2015 at 20:04
Sign up to request clarification or add additional context in comments.

1 Comment

That actually made the trick. I'm running this on OS X. Thanks for your explanation as well.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.