2

When I read the How TCP backlog works in Linux, I see the following question in the comment without an explanation. Here is a simple test socket server.

#! /usr/bin/env python
# -*- coding: utf-8 -*-
import socket

HOST = ''
PORT = 9999

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(1)

while 1:
    pass

Mac os

First, Run server on my macOS and use nc to connect to the server, the behavior is:

  1. accept the first nc connection
  2. the second nc connection is hanging and resending the SYN packet.

Which is just as expected.

Mac OS

Because:

Historically, BSD derived TCP implementations use the first approach. That choice implies that when the maximum backlog is reached, the system will no longer send back SYN/ACK packets in response to SYN packets. Usually the TCP implementation will simply drop the SYN packet (instead of responding with a RST packet) so that the client will retry.

Centos 7(Linux)

Then run it on a Linux machine to do the same thing, the behavior is:

  1. accept the first connection.
  2. accept the second connection!
  3. the third connection hangs and resending the ACK packet, the server at the same time, resending the SYN/ACK.

The second connection is established somehow.

Linux

The question is, why the server can accept 2 connections on Linux and only one on macOS.

The relevant question

Steffen Ullrich mark it as same with another question: listen() ignores the backlog argument?.

The backlog argument provides a hint to the implementation which the implementation shall use to limit the number of outstanding connections in the socket's listen queue.

It seems true. But at the same time, python doc says:

socket.listen(backlog) Listen for connections made to the socket. The backlog argument specifies the maximum number of queued connections and should be at least 0; the maximum value is system-dependent (usually 5), the minimum value is forced to 0.

Then maybe the python implementation just use backlog as a hint? The backlog is not the number of the connections the server would hold, but some func(backlog) is the number behind the back. Do anyone can have a certain explain? And why the maximum value is usually 5?

PS:

when set backlog=2, the fourth connections will be hang. when set backlog=5, the sixth connections will be hang.

selfboot
  • 1,490
  • 18
  • 23
  • @selfboot Linux seem to allow `backlog + 1` connections, atleast for a backlog of 1,2 and 3. You can test it yourself - how many nc connections are established if you do listen(2), How many if you do listen(3) and so on. It may be the question Steffen links to is correct too, it states the backlog is rounded up to the nearest power of 2 - though that does not match what I observe. It may even depend no the kernel version – nos May 29 '17 at 08:12
  • The system is free to adjust the specified backlog up or down: usually up, and these days often with a minimum of 50, if not 500. The *original* BSD minimum was 5, in 1983. – user207421 May 29 '17 at 08:26
  • I have test backlog=2, then the fourth connection hangs and resending the ACK packet. It seems python socket allow backlog + 1 connections. – selfboot May 29 '17 at 08:31
  • It has nothing to do with Python whatsoever. It is a matter of the operating system's implementation of TCP. – user207421 May 29 '17 at 09:56
  • @selfboot It is the same if you translate the code to C – hbprotoss Dec 28 '18 at 13:04

0 Answers0