When does socket.recv(recv_size) return in Python?

Based on my tests, I concluded that socket.recv(recv_size) returns in the following three scenarios:

  1. After the connection is closed: For example, when the client side calls socket.close() or when any socket error occurs, it will return an empty string.
  2. When some data arrives and its size exceeds recv_size: If data is available that is larger than the specified recv_size, the function will return the data in chunks, up to the limit set by recv_size.
  3. When some data arrives, its size is smaller than recv_size, and no more data arrives after a short period: In this case, recv() returns the available data when no further data is expected. I found that a short delay of 0.1 seconds often works.

More details about #3:

  • server.py:
while True:
    data = sock.recv(10)
    print(data, 'EOF')
  • client1.py:
sock.sendall("12345")
sock.sendall("a" * 50)
  • client2.py:
sock.sendall("12345")
time.sleep(0.1)
sock.sendall("a" * 50)

When I run client1.py, the server echoes:

12345aaaaa EOF
aaaaaaaaaa EOF
aaaaaaaaaa EOF
aaaaaaaaaa EOF
aaaaaaaaaa EOF
aaaaa EOF

When I run client2.py, the server echoes:

12345 EOF
aaaaaaaaaa EOF
aaaaaaaaaa EOF
aaaaaaaaaa EOF
aaaaaaaaaa EOF
aaaaaaaaaa EOF

Are my conclusions correct? Where can I find the official description regarding the behavior described in #3 for python socket recv?

The socket.recv(recv_size) function in Python operates based on several conditions. It returns data based on the following factors:

  • Connection closure: When the remote side closes the connection, recv() returns an empty string (b"" in Python 3) to indicate that no more data will be received.
  • Data size exceeds recv_size: If the data received is larger than the specified recv_size, recv() returns only the data corresponding to recv_size. Further calls to recv() will be needed to retrieve the remaining data.
  • Data smaller than recv_size with a small delay: When the data received is smaller than recv_size, and there is no more data within a short period (usually a timeout threshold), recv() returns the data it has received. A short timeout (like 0.1s) can help confirm that no more data will arrive.

For official descriptions of how recv() handles these cases, you can refer to the Python socket.recv documentation in the official Python docs, specifically the section about non-blocking and buffered I/O behavior.

In Python, the behavior of socket.recv() can sometimes be confusing due to its interaction with buffers and timing. Specifically:

  • Empty string on connection closure: After the server or client calls socket.close(), recv() will return an empty string, signaling that the connection is closed.
  • Partial data retrieval: When receiving data, recv() might return only part of the data if it’s larger than recv_size. For example, sending a large chunk of data but limiting recv_size to 10 bytes means you need multiple calls to fully receive the data.
  • Data is smaller than recv_size and no new data arrives: After a small delay (0.1s), recv() will return the data it has received if no more data is expected.

To better understand this, check out the Python socket recv documentation for specifics on non-blocking sockets, timeouts, and buffer handling.

When using recv() in Python, understanding the timing and buffering behavior is essential:

  • Connection closure results in empty string: When the other side of the connection closes the socket, recv() will return an empty string to signify the end of data transmission.
  • When data is larger than recv_size: If the data sent exceeds the recv_size, recv() will only return a portion of the data. Additional calls will be required to get the remaining data.
  • Smaller data chunks with no more data: If the data received is smaller than recv_size and no new data arrives within a short timeout period (like 0.1 seconds), recv() will return the available data. You can adjust the timeout period based on your needs.

For official guidelines and edge cases, refer to the Python socket recv section of the Python documentation, which provides detailed information about socket states and data reception.