简体   繁体   中英

Socket waiting for connection timeout

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM