免费注册 查看新帖 |

Chinaunix

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

求助:linux下socket编程的backlog参数的问题【已解决】 [复制链接]

论坛徽章:
1
IT运维版块每日发帖之星
日期:2015-11-17 06:20:00
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-07-02 13:51 |只看该作者 |倒序浏览
本帖最后由 jiufei19 于 2012-06-03 15:36 编辑

进行socket编程时, 我们都知道服务器端要进入listen状态,即如下代码所示:

103     if(listen(sockfd, 5)==-1){
                ...
             }

上述listen系统调用的参数5就是backlog参数,根据TCPIP Illustrated卷1的说明,该参数规定了TCP层可以容纳的连接请求队列长度(应用层尚未进行处理),并且给出了一个示例来说明该参数的具体效果,作为对照,我在fedora 8中也进行了类似实验,程序在上述listen执行后中断下来,并且将backlog参数设置为1,结果发现linux下似乎该参数没有什么作用, 超过2个客户端发来的连接请求仍然可以被处理(不过好像第3个客户端的处理和前2个略有不同),而不是像卷1中描述的那样,超过backlog规定数目客户端需要不停发SYN进行连接尝试。

下面是我用tcpdump抓包后的结果,192.168.1.137是服务器端, 192.168.146.1 是客户端,可以看到前3组似乎都完成了3次握手,但是从第3组开始,服务器端不停发出SYN分段

IP 192.168.146.1.veritas-ucl > 192.168.1.137.cslistener: S 1365328955:1365328955(0) win 64240 <mss 1460>
IP 192.168.1.137.cslistener > 192.168.146.1.veritas-ucl: S 2551711032:2551711032(0) ack 1365328956 win 5840 <mss 1460>
IP 192.168.146.1.veritas-ucl > 192.168.1.137.cslistener: . ack 2551711033 win 64240

IP 192.168.146.1.2153 > 192.168.1.137.cslistener: S 1339035798:1339035798(0) win 64240 <mss 1460>
IP 192.168.1.137.cslistener > 192.168.146.1.2153: S 2781121692:2781121692(0) ack 1339035799 win 5840 <mss 1460>
IP 192.168.146.1.2153 > 192.168.1.137.cslistener: . ack 2781121693 win 64240

IP 192.168.146.1.2154 > 192.168.1.137.cslistener: S 870525075:870525075(0) win 64240 <mss 1460>
IP 192.168.1.137.cslistener > 192.168.146.1.2154: S 2986811472:2986811472(0) ack 870525076 win 5840 <mss 1460>
IP 192.168.146.1.2154 > 192.168.1.137.cslistener: . ack 2986811473 win 64240

IP 192.168.1.137.cslistener > 192.168.146.1.2154: S 2986811472:2986811472(0) ack 870525076 win 5840 <mss 1460>
IP 192.168.146.1.2154 > 192.168.1.137.cslistener: . ack 2986811473 win 64240
IP 192.168.1.137.cslistener > 192.168.146.1.2154: S 2986811472:2986811472(0) ack 870525076 win 5840 <mss 1460>
IP 192.168.146.1.2154 > 192.168.1.137.cslistener: . ack 2986811473 win 64240
IP 192.168.1.137.cslistener > 192.168.146.1.2154: S 2986811472:2986811472(0) ack 870525076 win 5840 <mss 1460>
IP 192.168.146.1.2154 > 192.168.1.137.cslistener: . ack 2986811473 win 64240
IP 192.168.1.137.cslistener > 192.168.146.1.2154: S 2986811472:2986811472(0) ack 870525076 win 5840 <mss 1460>
IP 192.168.146.1.2154 > 192.168.1.137.cslistener: . ack 2986811473 win 64240
IP 192.168.1.137.cslistener > 192.168.146.1.2154: S 2986811472:2986811472(0) ack 870525076 win 5840 <mss 1460>
IP 192.168.146.1.2154 > 192.168.1.137.cslistener: . ack 2986811473 win 64240

上述结果我无法理解,请教各位帮忙解释下

[ 本帖最后由 jiufei19 于 2009-7-3 17:54 编辑 ]

论坛徽章:
0
2 [报告]
发表于 2009-07-02 15:27 |只看该作者

回复 #1 jiufei19 的帖子

理论啥时候都是理论吧,呵呵,人家linux就这么实现,你待咋地?!
linux的listen的这个参数存放建立成功的连接数。
按道理说应该超过就不行了,可人家就行,你也别叫这个真。
就像端口复用,明明理论上处于CLOSE_WAIT状态是可以端口复用的,可人家就不行,没辙。

[ 本帖最后由 urapple 于 2009-7-3 09:33 编辑 ]

论坛徽章:
5
2015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:53:172015亚冠之水原三星
日期:2015-06-02 16:34:202015年亚冠纪念徽章
日期:2015-10-19 18:13:37程序设计版块每日发帖之星
日期:2015-11-08 06:20:00
3 [报告]
发表于 2009-07-02 16:22 |只看该作者
原帖由 urapple 于 2009-7-2 15:27 发表
理论啥时候都是理论吧,呵呵,人家linux就这么实现,你待咋地?!
linux的listen的这个参数存放建立成功的连接数。
按道理说应该超过就不行了,可人家就行,你也别叫这个真。
就像端口复用,明明理 ...


linux的listen的这个参数存放建立成功的连接数。 就是在客户端看来connect()成功,但是服务端没有accept()的连接么? 这么理解是否正确?

论坛徽章:
0
4 [报告]
发表于 2009-07-02 16:29 |只看该作者
原帖由 xinglp 于 2009-7-2 16:22 发表


linux的listen的这个参数存放建立成功的连接数。 就是在客户端看来connect()成功,但是服务端没有accept()的连接么? 这么理解是否正确?




listen那个数字叫积压值,有一个表,表示的积压值与listen队列长度的映射关系

三次握手后connect就能返回
accept只是把tcp链接请求从请求队列中移出来,给以后的连接请求腾出地方

论坛徽章:
0
5 [报告]
发表于 2009-07-02 16:57 |只看该作者

回复 #4 astezheng 的帖子

恩,应该是这样,没accept拿出来用之前,应该是你backlog是几就允许几个等着,但人家linux就是没这么干,你又能拿他怎样!
也不知道这算不算他的bug:wink:

论坛徽章:
0
6 [报告]
发表于 2009-07-02 18:13 |只看该作者
首先tcp的队列有两个:1是未连接队列,2是已连接队列。当客户端连接服务端时先在未连接队列里面建立一条记录,等tcp三次握手完成后把记录从未连接队列中移到已连接队列。
你测试的这种情况应该是:已连接队列和未连接队列都满了,这时如果客户的syn到达,则服务器tcp将忽略此分节,且不回送rst,而客户端tcp将重发之前的syn分节,就会导致你所说的情况。另外,listen的参数并不绝对准确,它只是个参考值,各操作系统实现都不一样,详情请看unp第二版p81。

论坛徽章:
1
IT运维版块每日发帖之星
日期:2015-11-17 06:20:00
7 [报告]
发表于 2009-07-02 22:40 |只看该作者

回复 #6 wwdwwd 的帖子

感谢答复,不过仍然有一个疑问,即我给出的测试例子中从第3组分段数据可以看出,这个第3个客户端发来的syn还是被服务器的tcp协议层正确响应了,即完成了3次握手,之后是服务器端的tcp不停的发送syn,而客户端对服务器发来的syn进行ack确认,而不是通常我们认为的客户端不停发送syn,服务器不予理睬。

论坛徽章:
0
8 [报告]
发表于 2009-07-03 11:20 |只看该作者
你在哪里抓的包,客户端,还是服务器端。


你要搞清楚,服务器端发的是syn+ack 不是syn
显然是服务器端没有认ack包,so 一直发syn+ack

论坛徽章:
1
IT运维版块每日发帖之星
日期:2015-11-17 06:20:00
9 [报告]
发表于 2009-07-03 17:37 |只看该作者

回复 #8 hritian 的帖子

感谢hritian提醒,我又仔细观察了linux下backlog值和连接数目的关系,得到如下结论:

1、我是在服务器端抓的包

2、的确服务器是发送的syn+ack,不是syn。

3、当backlog为1时,完全正确3次握手的数目是2,从第3个连接开始,就发生了服务器端tcp将对第3个客户tcp连接请求不停发送syn+ack的现象(若backlog为2,则从第4个连接开始,若backlog为3,则从第5个连接开始),因此问题似乎已经很明显了,即第3个连接从服务器端tcp来看(backlog为1),似乎是一个过载的连接,不过如果从客户端tcp来看,既然已经发生了最初的3次握手,那么应该说连接已经建立了呀,至于随后服务器tcp不停发来的syn+ack,客户端难道还关心吗?换句话讲,应该是对于第3个客户端发来的tcp连接,服务器端根本不应答syn+ack才合理,所以这里还有最后一个疑问

[ 本帖最后由 jiufei19 于 2009-7-3 21:54 编辑 ]

论坛徽章:
0
10 [报告]
发表于 2009-07-03 19:57 |只看该作者
原帖由 jiufei19 于 2009-7-3 17:37 发表
感谢hritian提醒,我又仔细观察了linux下backlog值和连接数目的关系,得到如下结论:

1、我是在服务器端抓的包

2、的确服务器是发送的syn+ack,不是syn。

3、当backlog为1时,完全正确3次握手的数目是 ...

同问
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP