listen() 忽略 backlog 参数?

Posted

技术标签:

【中文标题】listen() 忽略 backlog 参数?【英文标题】:listen() ignores the backlog argument? 【发布时间】:2011-07-03 22:05:12 【问题描述】:

我有以下问题:

我有sockfd = socket(AF_INET, SOCK_STREAM, 0)

在我设置和绑定套接字之后(假设是sockfd.sin_port = htons(666)),我立即这样做:

listen(sockfd, 3);

sleep(50); // for test purposes

我睡了 50 秒来测试 backlog 参数,这似乎被忽略了,因为我可以在端口 666 上建立连接* 3 次以上。

*:我的意思是,对于从客户端发送的每个第 N 个 SYN (n>3),我都会获得一个 syn/ack,并将其放置在侦听队列中,而不是被丢弃。有什么问题?我已经阅读了 listen(2) 和 tcp(7) 的手册页,发现:

在 Linux 2.2 中,TCP 套接字上的 backlog 参数的行为发生了变化。 现在它指定等待接受的完全建立的套接字的队列长度,而不是不完整的连接请求的数量。不完整套接字队列的最大长度可以 使用 /proc/sys/net/ipv4/tcp_max_syn_backlog。 当启用 syncookies 时, 没有逻辑最大长度,这 设置被忽略。参见 tcp(7) 更多的 信息。

,但即使使用sysctl -w sys.net.ipv4.tcp_max_syn_backlog=2sysctl -w net.ipv4.tcp_syncookies=0,我仍然得到相同的结果!我一定是遗漏了什么或者完全误解了listen() 的积压目的。

【问题讨论】:

【参考方案1】:

listen() 的积压参数只是建议性的。

POSIX says:

积压参数提供了一个提示 实施该 实施应使用来限制 中的未完成连接数 套接字的监听队列。

当前版本的 Linux 内核将其四舍五入为 2 的次幂,最小为 16。相关代码位于 reqsk_queue_alloc()。

【讨论】:

您知道是否有原因将最小值设置为 16,而不是 1? 这并不完全正确。函数 reqsk_queue_alloc() 计算表分配的值,但在函数 inet_listen() 中分配给 sk->sk_max_ack_backlog 的积压值,这里使用该值: static inline int sk_acceptq_is_full(struct sock *sk) return sk->sk_ack_backlog > sk->sk_max_ack_backlog; 我正在使用 Ubuntu。如果我没有误解你,当我将backlog 设置为 1 时,它会向上取整为 2(这是 2 的下一个最高幂)。但是当我用backlog 1 调用listen 时,我可以成功创建100 个到套接字的连接。 @Marisha 请尝试将内核关键字添加到您的搜索中。 :) @amn:Linux 确实使用 POSIX 语义作为指导,特别是在套接字接口的情况下。无论如何,我的回答还包括实际的 Linux 行为以及实现它的源代码的链接,我认为这非常明确地回答了特定于 Linux 的上下文中的问题。【参考方案2】:

不同的操作系统提供不同数量的排队连接和不同的积压数。 FreeBSD 似乎是少数几个实际上具有一对一映射的操作系统之一。 (来源: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)

【讨论】:

同一个消息来源说,基于伯克利的操作系统将积压工作乘以 1.5 并为此提供一个队列,但这样做的原因“已被历史遗忘”。这个新的源链接将您指向它说的特定页面:(来源:books.google.com/…)

以上是关于listen() 忽略 backlog 参数?的主要内容,如果未能解决你的问题,请参考以下文章

listen 函数中参数 backlog

listen()函数中backlog参数分析

如何确定socket listen() backlog 参数的值?

[python]socket.listen(backlog)中的backlog含义

socket_listen里面第二个参数backlog的用处

linux 下listen调用的backlog设为0,有何意义