listen() ignores the backlog argument?

10,427

Solution 1

The backlog argument to listen() is only advisory.

POSIX says:

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 )

Share:
10,427

Related videos on Youtube

Markoff Chaney
Author by

Markoff Chaney

Updated on February 25, 2020

Comments

  • Markoff Chaney
    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 and sysctl -w net.ipv4.tcp_syncookies=0, I still get the same results! I must be missing something or completely missunderstand listen()'s backlog purpose.

  • gpcz
    gpcz about 13 years
    The 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
    gojomo about 11 years
    Do you know if there's a reason to set a minimum of 16, as opposed to say 1?
  • Nikolai
    Nikolai about 10 years
    This 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
    satoru almost 10 years
    I 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 call listen with backlog 1, I can create 100 connections to the socket successfully.
  • sonus21
    sonus21 about 9 years
    @satoru IMO it gives a hint for maximum number of clients waiting for connection .
  • Marisha
    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
    Marisha over 4 years
    @Nikolai, I want to understand your comment, I've searched for inet_listen() but find on web staff for Apple https://opensource.apple.com/source/postfix/postfix-144/post‌​fix/src/util/inet_li‌​sten.c.auto.html, but the question has tag Linux. Any idea why is that?
  • Marisha
    Marisha over 4 years
    @satoru, also, it will set to 16 (minimum), not 2 (btw 1 is also power of 2 == 2^0)
  • Nikolai
    Nikolai over 4 years
    @Marisha please try to add kernel keyword to your search. :)
  • Armen Michaeli
    Armen Michaeli over 2 years
    Linux 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
    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.