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

PythonSocketsTimeout

Python Problem Overview


I need to set timeout on python's socket recv method. How to do it?

Python Solutions


Solution 1 - Python

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.

Solution 2 - Python

Solution 3 - Python

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)

Solution 4 - Python

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)

Solution 5 - Python

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)

Solution 6 - Python

try this it uses the underlying C.

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

Solution 7 - Python

You can use socket.settimeout() which accepts a integer argument representing number of seconds. For example, socket.settimeout(1) will set the timeout to 1 second

Solution 8 - Python

Got a bit confused from the top answers so I've wrote a small gist with examples for better understanding.


Option #1 - socket.settimeout()

Will raise an exception in case the sock.recv() waits for more than the defined timeout.

import socket

sock = socket.create_connection(('neverssl.com', 80))
timeout_seconds = 2
sock.settimeout(timeout_seconds)
sock.send(b'GET / HTTP/1.1\r\nHost: neverssl.com\r\n\r\n')
data = sock.recv(4096)
data = sock.recv(4096) # <- will raise a socket.timeout exception here

Option #2 - select.select()

Waits until data is sent until the timeout is reached. I've tweaked Daniel's answer so it will raise an exception

import select
import socket

def recv_timeout(sock, bytes_to_read, timeout_seconds):
    sock.setblocking(0)
    ready = select.select([sock], [], [], timeout_seconds)
    if ready[0]:
        return sock.recv(bytes_to_read)

    raise socket.timeout()

sock = socket.create_connection(('neverssl.com', 80))
timeout_seconds = 2
sock.send(b'GET / HTTP/1.1\r\nHost: neverssl.com\r\n\r\n')
data = recv_timeout(sock, 4096, timeout_seconds)
data = recv_timeout(sock, 4096, timeout_seconds) # <- will raise a socket.timeout exception here

Solution 9 - Python

As mentioned in previous replies, you can use something like: .settimeout() For example:

import socket

s = socket.socket()

s.settimeout(1) # Sets the socket to timeout after 1 second of no activity

host, port = "somehost", 4444
s.connect((host, port))

s.send("Hello World!\r\n")

try:
    rec = s.recv(100) # try to receive 100 bytes
except socket.timeout: # fail after 1 second of no activity
    print("Didn't receive data! [Timeout]")
finally:
    s.close()

I hope this helps!!

Solution 10 - Python

#! /usr/bin/python3.6

# -*- coding: utf-8 -*-
import socket
import time
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
s.settimeout(5)
PORT = 10801

s.bind(('', PORT))
print('Listening for broadcast at ', s.getsockname())
BUFFER_SIZE = 4096
while True:
    try:
        data, address = s.recvfrom(BUFFER_SIZE)
    except socket.timeout:
        print("Didn't receive data! [Timeout 5s]")
        continue

Solution 11 - Python

Shout out to: https://boltons.readthedocs.io/en/latest/socketutils.html

It provides a buffered socket, this provides a lot of very useful functionality such as:

.recv_until()    #recv until occurrence of bytes
.recv_closed()   #recv until close
.peek()          #peek at buffer but don't pop values
.settimeout()    #configure timeout (including recv timeout)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionThorellerView Question on Stackoverflow
Solution 1 - PythonDaniel StutzbachView Answer on Stackoverflow
Solution 2 - PythonnoskloView Answer on Stackoverflow
Solution 3 - PythonubershmekelView Answer on Stackoverflow
Solution 4 - PythonnorikoView Answer on Stackoverflow
Solution 5 - PythonValaView Answer on Stackoverflow
Solution 6 - PythonMohammad AlkhaldiView Answer on Stackoverflow
Solution 7 - PythonBrian ZhengView Answer on Stackoverflow
Solution 8 - PythonJossef Harush KadouriView Answer on Stackoverflow
Solution 9 - PythonmeepView Answer on Stackoverflow
Solution 10 - PythonshengView Answer on Stackoverflow
Solution 11 - PythonCaesurusView Answer on Stackoverflow