如果在Linux中使用TCP,则listen的待办事项编号是否包括SYN接收的连接计数?

nar*_*llo 7 c sockets networking tcp linux-kernel

我阅读了一些文章,并检查了inet_listen()-> inet_csk_listen_start()等Linux内核代码,看来syscall的backlog参数listen()只影响接受的队列,而不影响 SYN接收的队列:

sk->sk_max_ack_backlog = backlog;
Run Code Online (Sandbox Code Playgroud)

即象征意义accept-queue + syn-received-queue != backlog。我不知道发生了什么事。本文指出:

接受和SYN队列的最大允许长度取自应用程序传递给listen(2)syscall的backlog参数。

但是MAN页中没有类似的东西。

此外,在Linux的情况下:是backlog的提示,提到这里也确实限制了队列?

red*_*0ct 6

如果是 4.3 内核,您指定的内容类似于:

tcp_v4_do_rcv()-> tcp_rcv_state_process()-> tcp_v4_conn_request()-> tcp_conn_request()->inet_csk_reqsk_queue_is_full()

在这里我们可以看到关于队列的最重要的细节:

/* TW buckets are converted to open requests without
 * limitations, they conserve resources and peer is
 * evidently real one.
 */
if ((sysctl_tcp_syncookies == 2 ||
     inet_csk_reqsk_queue_is_full(sk)) && !isn) {
    want_cookie = tcp_syn_flood_action(sk, skb, rsk_ops->slab_name);
    if (!want_cookie)
        goto drop;
}

/* Accept backlog is full. If we have already queued enough
 * of warm entries in syn queue, drop request. It is better than
 * clogging syn queue with openreqs with exponentially increasing
 * timeout.
 */
if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1) {
    NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS);
    goto drop;
}
Run Code Online (Sandbox Code Playgroud)

请注意inet_csk_reqsk_queue_is_full()

static inline int inet_csk_reqsk_queue_is_full(const struct sock *sk)
{
    return inet_csk_reqsk_queue_len(sk) >= sk->sk_max_ack_backlog;
}
Run Code Online (Sandbox Code Playgroud)

最后,它将当前队列icsk_accept_queuesk_max_ack_backlog之前设置的大小进行比较inet_csk_listen_start()。所以是的,在当前情况下backlog会影响传入队列

您可以看到两者sk_acceptq_is_full()inet_csk_reqsk_queue_is_full()sk_max_ack_backlog通过以下设置的相同套接字进行比较listen()

static inline bool sk_acceptq_is_full(const struct sock *sk)
{
    return sk->sk_ack_backlog > sk->sk_max_ack_backlog;
}
Run Code Online (Sandbox Code Playgroud)

有用的链接:1 , 2