Search code examples
pythonsocketsrecv

Why won't Python's socket.recv() return -1


If I close a server socket while in a s.recv_into() loop from a client, I keep getting 0 from recv_into() infinitely.

As I understand, the only way to know a socket is closed was not through the Python socket mechanism itself, but using select / poll / etc.

What's the rational of not returning -1 when the socket is closed by the other side? Why can't I properly differentiate "no data currently" from "no one there anymore"?

EDIT:

Perhaps the correct question is - why is no exception thrown when using recv(), if the other side terminated the connection?


Solution

  • The recv_into is just a wrapper of the C system call by name recv. The return value of 0 is not an erroneous condition!

    From Linux manuals, recv(2):

    RETURN VALUE

    These calls return the number of bytes received, or -1 if an error occurred. In the event of an error, errno is set to indicate the error.

    When a stream socket peer has performed an orderly shutdown, the return value will be 0 (the traditional "end-of-file" return).

    Datagram sockets in various domains (e.g., the UNIX and Internet domains) permit zero-length datagrams. When such a datagram is received, the return value is 0.

    The value 0 may also be returned if the requested number of bytes to receive from a stream socket was 0.

    For error cases, Python will not return -1, instead it will raise an appropriate exception.

    For a stream sockets you must break the loop whenever recv_* returns a value that indicates that 0 bytes were received. There is no point for checking -1, but in case you do want to be extra certain, you can naturally use while sock.recv_into(....) > 0: or similar.

    The various read calls in Python work in similar fashion.