jehozm
jehozm

Reputation: 23

Python socket won't timeout

I'm having an issue with Python's socket module that I haven't been able to find anywhere else.

I'm building a simple TCP chat client, and while it successfully connects to the server initially, the script hangs endlessly on sock.recv() despite the fact that I explicitly set a timeout length.

I've tried using different timeout values and including setblocking(False) but no matter what I do it keeps acting like the socket is in blocking mode.

Here are the relevant parts of my code:

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

def listen_to_server():
    global connected

    while connected:
        ready_to_read, ready_to_write, in_error = select.select([sock], [], [])

        if ready_to_read:
            try:
                data = sock.recv(1024)
            except socket.timeout:
                print('TIMEOUT')
            if not data:
                append_to_log('Disconnected from server.\n')
                connected = False
            else:
                append_to_log(str(data))

Any suggestions would be helpful, I'm at a total loss here.

Upvotes: 2

Views: 4060

Answers (1)

Qeek
Qeek

Reputation: 1970

You've mixed two things the socket timeout and the select.

When you set socket timeout then you are telling to that socket: if I try do some operation (e.g. recv()) and it won't be finished until my limit then raise timeout exception.

The select takes file descriptors (on Windows only sockets) and start checking if the rlist (the first parameter) contains any socket ready to read (aka some data have arrived). If any data arrived then the program continues.

Now your code do this:

  1. Set timeout for socket operations
  2. Select start waiting for data (if you don't send them then they never arrives)

and that's it. You stuck at the select.

You should just call the recv() without select. Than your timeout should be applied.

If you need manage multiple sockets at once than you have to use select and set the 4th parameter timeout.

Upvotes: 2

Related Questions