listen() ignores the backlog argument?
Solution 1
The backlog argument to listen()
is only advisory.
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.
Current versions of the Linux kernel round it up to the next highest power of two, with a minimum of 16. The revelant code is in reqsk_queue_alloc().
Solution 2
Different operating systems provide different numbers of queued connections with different backlog numbers. FreeBSD appears to be one of the few OSes that actually has a 1-to-1 mapping. (source: http://books.google.com/books?id=ptSC4LpwGA0C&lpg=PA108&ots=Kq9FQogkTr&dq=berkeley%20listen%20backlog%20ack&pg=PA108#v=onepage&q=berkeley%20listen%20backlog%20ack&f=false )
Related videos on Youtube
Markoff Chaney
Updated on February 25, 2020Comments
-
Markoff Chaney about 4 years
I have the following problem:
I have
sockfd = socket(AF_INET, SOCK_STREAM, 0)
After I set up and bind the socket (let's say with
sockfd.sin_port = htons(666)
), I immediately do:listen(sockfd, 3); sleep(50); // for test purposes
I'm sleeping for 50 seconds to test the backlog argument, which seems to be ignored because I can establish a connection* more than 3 times on port 666.
*: What I mean is that I get a syn/ack for each Nth SYN (n>3) sent from the client and placed in the listen queue, instead of being dropped. What could be wrong? I've read the man pages of listen(2) and tcp(7) and found:
The behavior of the backlog argument on TCP sockets changed with Linux 2.2. Now it specifies the queue length for completely established sockets waiting to be accepted, instead of the number of incomplete connection requests. The maximum length of the queue for incomplete sockets can be set using /proc/sys/net/ipv4/tcp_max_syn_backlog. When syncookies are enabled there is no logical maximum length and this setting is ignored. See tcp(7) for more information.
, but even with
sysctl -w sys.net.ipv4.tcp_max_syn_backlog=2
andsysctl -w net.ipv4.tcp_syncookies=0
, I still get the same results! I must be missing something or completely missunderstandlisten()
's backlog purpose. -
gpcz about 13 yearsThe same source says that Berkeley-based OSes multiply backlog by 1.5 and give a queue for that, but that the reasons for doing so are "lost to history". This new source link points you to the specific page where it says that: (source: books.google.com/… )
-
gojomo about 11 yearsDo you know if there's a reason to set a minimum of 16, as opposed to say 1?
-
Nikolai about 10 yearsThis is not entirely correct. Function reqsk_queue_alloc() compute value for table allocation, but in the function inet_listen() value of backlog assigned to sk->sk_max_ack_backlog and this value is used here: static inline int sk_acceptq_is_full(struct sock *sk) { return sk->sk_ack_backlog > sk->sk_max_ack_backlog; }
-
satoru almost 10 yearsI am using Ubuntu. If I didn't misunderstand you, when I set
backlog
to 1, it will be rounded up to 2 (which is the next highest power of two). But event when I calllisten
withbacklog
1, I can create 100 connections to the socket successfully. -
sonus21 about 9 years@satoru IMO it gives a hint for maximum number of clients waiting for connection .
-
Marisha over 4 years@satoru, maybe your system is as per cited man page:
When syncookies are enabled there is no logical maximum length and this setting is ignored.
-
Marisha over 4 years@Nikolai, I want to understand your comment, I've searched for
inet_listen()
but find on web staff for Applehttps://opensource.apple.com/source/postfix/postfix-144/postfix/src/util/inet_listen.c.auto.html
, but the question has tagLinux
. Any idea why is that? -
Marisha over 4 years@satoru, also, it will set to 16 (minimum), not 2 (btw 1 is also power of 2 == 2^0)
-
Nikolai over 4 years@Marisha please try to add kernel keyword to your search. :)
-
Armen Michaeli over 2 yearsLinux isn't necessarily POSIX compliant, nor does it declare such compliance. As much as your answer is indeed very useful in context of POSIX, the question is tagged with "linux" explicitly.
-
caf over 2 years@amn: Linux does use the POSIX semantics as guidance, particularly in the case of the sockets interface. Regardless, my answer also included the actual Linux behaviour with a link to the source code that implements it, which I think pretty conclusively answers the question in a Linux-specific context.