免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 5402 | 回复: 7
打印 上一主题 下一主题

为什么socket.listen的backlog参数比实际少1 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2014-02-02 18:01 |只看该作者 |倒序浏览
在2.6中backlog最少是1,在2.7之后,backlog最少是0,设为0时,socket等待队列却能容纳1个连接,这是为什么?

论坛徽章:
0
2 [报告]
发表于 2014-02-02 22:21 |只看该作者
帮顶                           

论坛徽章:
3
天蝎座
日期:2014-10-25 13:44:312015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:48:31
3 [报告]
发表于 2014-02-03 01:47 |只看该作者
LZ应该知道backlog是干啥用的哦(如不清楚可百度)

LWIP的代码如下,linux的没查,

  lpcb->backlog = (backlog ? backlog : 1);

论坛徽章:
0
4 [报告]
发表于 2014-02-03 12:13 |只看该作者
回复 3# ilex


    backlog为0的时候,等待队列可以有1个客户连接,backlog为1的时候,等待队列可以容纳2个连接,这和backlog作用不符呀?python2.6的时候backlog最低为1,python2.7就改成最低为0了,2.7的changelog里面也没找到相关的详细说明

论坛徽章:
3
天蝎座
日期:2014-10-25 13:44:312015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:48:31
5 [报告]
发表于 2014-02-05 00:15 |只看该作者
说实话,从没看过linux的内核代码,

特意查了一下linux有关backlog的代码,我猜和下面有关:

A、处理收到的connect请求:
static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
                               int addr_len, int flags)
{

line1067                if (unix_recvq_full(other)) {
                               校验backlog失败,报错;
                       }
}

B:校验队列是否超过backlog
static inline int unix_recvq_full(struct sock const *sk)
{
        return skb_queue_len(&sk->sk_receive_queue) > sk->sk_max_ack_backlog;
}
——这个函数看起来是比较sk_receive_queue队列的长度和socket设置的backlog值,用的是>而不是>=

C:sk_receive_queue队列在如下增长:
line 1156
        /* take ten and and send info to listening sock */
        spin_lock(&other->sk_receive_queue.lock);
        __skb_queue_tail(&other->sk_receive_queue, skb);
        spin_unlock(&other->sk_receive_queue.lock);
        unix_state_unlock(other);
        other->sk_data_ready(other, 0);
        sock_put(other);
        return 0;

3、上面两处行号,是在af_unix.c文件中。
     也就是说:先看队列满(超)了没,再入队列。
     当设置为1时,
     收到第一个sync,看到队列有0个,此时没超,入队列,队列长==1。
     再收到一个sync,看到队列有1个,此时没超,入队列,队列长==2。

4、对于设置backlog==0,就先不讨论了,可以试一下设置为1时:c/c++是什么效果,和python是否一样的效果?
     看起来和python无关,倒是操作系统/TCPIP相关的问题吧?



linux文件太多,不知道从哪看起,根据感觉在sourcinsight瞎猜的,说错了别笑话。。。

论坛徽章:
3
天蝎座
日期:2014-10-25 13:44:312015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:48:31
6 [报告]
发表于 2014-02-05 00:48 |只看该作者
好像找错了代码,感觉和下面几个函数有关:
static inline void sk_acceptq_added(struct sock *sk)
{
        sk->sk_ack_backlog++;
}

static inline int sk_acceptq_is_full(struct sock *sk)
{
        return sk->sk_ack_backlog > sk->sk_max_ack_backlog;
}


太晚了,以后再找。

论坛徽章:
3
天蝎座
日期:2014-10-25 13:44:312015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:48:31
7 [报告]
发表于 2014-02-06 07:56 |只看该作者
刚看了一下,猜测和上面2个函数有关,

/*
*        Process an incoming packet for SYN_RECV sockets represented
*        as a request_sock.
*/

struct sock *tcp_check_req(struct sock *sk,struct sk_buff *skb,
                           struct request_sock *req,
                           struct request_sock **prev)
{

}
tcp_check_req【先】调用
                child = inet_csk(sk)->icsk_af_ops->syn_recv_sock(sk, skb,
                                                                 req, NULL);
在->syn_recv_sock里面调用sk_acceptq_is_full(struct sock *sk),检查是否超过了backlog

tcp_check_req【再】调用inet_csk_reqsk_queue_add(sk, req, child);,把SYN挂到链表中。

论坛徽章:
3
射手座
日期:2014-08-18 12:15:53戌狗
日期:2014-08-22 09:53:36寅虎
日期:2014-08-22 14:15:29
8 [报告]
发表于 2014-02-08 22:26 |只看该作者
这个问题跟python 本身没关系, 是linux内核实现的问题,就是楼上说的原因,是sk_acceptq_is_full的问题,
sk->sk_max_ack_backlog就是listen设置的backlog值,sk->sk_ack_backlog是当前backlog长度,
注意他用的是大于比较,就是说等于的时候他不认为是full的,还会继续接受链接,因此用netstat看到的最大连接数永远是backlog+1。

其实这是linux内核的小bug,不过没什么大问题。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP