Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set timeout on python's socket recv method?

People also ask

How do you set a recv timeout?

The typical approach is to use select() to wait until data is available or until the timeout occurs. Only call recv() when data is actually available. To be safe, we also set the socket to non-blocking mode to guarantee that recv() will never block indefinitely.

How do you create a timeout in Python?

Use multiprocessing to timeout a Python function print('Starting function inc_forever()...') print(next(counter))def return_zero(): print('Starting function return_zero()...')

What is socket timeout Python?

Socket connection timeout High A new Python socket by default doesn't have a timeout. Its timeout defaults to None. Not setting the connection timeout parameter can result in blocking socket mode. In blocking mode, operations block until complete or the system returns an error.

How does Python socket recv work?

We use a while loop to process the received data. If no error occurs, recv returns the bytes received. If the connection has been gracefully closed, the return value is an empty byte string. The recv is a blocking method that blocks until it is done, or a timeout is reached or another exception occurs.


The typical approach is to use select() to wait until data is available or until the timeout occurs. Only call recv() when data is actually available. To be safe, we also set the socket to non-blocking mode to guarantee that recv() will never block indefinitely. select() can also be used to wait on more than one socket at a time.

import select

mysocket.setblocking(0)

ready = select.select([mysocket], [], [], timeout_in_seconds)
if ready[0]:
    data = mysocket.recv(4096)

If you have a lot of open file descriptors, poll() is a more efficient alternative to select().

Another option is to set a timeout for all operations on the socket using socket.settimeout(), but I see that you've explicitly rejected that solution in another answer.


there's socket.settimeout()


As mentioned both select.select() and socket.settimeout() will work.

Note you might need to call settimeout twice for your needs, e.g.

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(("",0))
sock.listen(1)
# accept can throw socket.timeout
sock.settimeout(5.0)
conn, addr = sock.accept()

# recv can throw socket.timeout
conn.settimeout(5.0)
conn.recv(1024)

You could set timeout before receiving the response and after having received the response set it back to None:

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

sock.settimeout(5.0)
data = sock.recv(1024)
sock.settimeout(None)

The timeout that you are looking for is the connection socket's timeout not the primary socket's, if you implement the server side. In other words, there is another timeout for the connection socket object, which is the output of socket.accept() method. Therefore:

sock.listen(1)
connection, client_address = sock.accept()
connection.settimeout(5)    # This is the one that affects recv() method.
connection.gettimeout()     # This should result 5
sock.gettimeout()           # This outputs None when not set previously, if I remember correctly.

If you implement the client side, it would be simple.

sock.connect(server_address)
sock.settimeout(3)

try this it uses the underlying C.

timeval = struct.pack('ll', 2, 100)
s.setsockopt(socket.SOL_SOCKET, socket.SO_RCVTIMEO, timeval)