免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 5726 | 回复: 12

tcp的粘包是怎么实现的? [复制链接]

论坛徽章:
0
发表于 2010-01-11 16:56 |显示全部楼层
20可用积分
我现在遇到一个奇怪的问题是,我在开发板上发送tcp数据,竟然发现没有任何的“粘包”。
我写了一个简单的测试程序,每次发送16 bytes的小数据,即反复的向tcp的socket中写入16 bytes的数据,然后在server端抓包,发现全是16 bytes 16bytes的小包。

同样的程序,在pc机上测试,会合并成大小不等的数据包发送出来。

理论上,tcp传输会将较小的数据合并在一起发送的,有人称之为“粘包”。

我想知道这个功能是怎么实现的?

或者谁知道这部分功能在内核代码的什么地方。

希望了解的指点一二。

谢谢了

论坛徽章:
0
发表于 2010-01-11 17:13 |显示全部楼层
原帖由 xpl 于 2010-1-11 16:56 发表
理论上,tcp传输会将较小的数据合并在一起发送的,有人称之为“粘包”。  

记得以前看资料,TCP 的实现方式不是所谓的 “把较小的数据包合并在一起发送”
实际上 TCP 内部有很多定时器,如果定时器没到,数据包在发送前又有新的过来,此时才可以合并
《TCP/IP 详解》卷一也有相关的说明
拿 telnet 举例,输入 asdfasdfasdfasdfasdfasdfasdfasdf 这样的字符,每隔一秒按一下的结果和复制、粘贴的结果就截然不同,后者就是所谓的“粘包”

论坛徽章:
0
发表于 2010-01-11 17:42 |显示全部楼层

回复 #2 platinum 的帖子

先谢谢白金了。

我对网络部分不是很了解,所以一时不知道该从那部分代码开始入手调。

我想知道tcp的这个定时器的具体工作方式,或者源码的位置,这样好调试我的kernel

论坛徽章:
0
发表于 2010-01-11 18:02 |显示全部楼层
出现粘包现象的原因是多方面的,它既可能由发送方造成,也可能由接收方造成。发送方引起的粘包是由TCP协议本身造成的,TCP为提高传输效率,发送方往往要收集到足够多的数据后才发送一包数据。若连续几次发送的数据都很少,通常TCP会根据优化算法把这些数据合成一包后一次发送出去,这样接收方就收到了粘包数据。接收方引起的粘包是由于接收方用户进程不及时接收数据,从而导致粘包现象。这是因为接收方先把收到的数据放在系统接收缓冲区,用户进程从该缓冲区取数据,若下一包数据到达时前一包数据尚未被用户进程取走,则下一包数据放到系统接收缓冲区时就接到前一包数据之后,而用户进程根据预先设定的缓冲区大小从系统接收缓冲区取数据,这样就一次取到了多包数据

论坛徽章:
0
发表于 2010-01-11 18:06 |显示全部楼层

回复 #4 ubuntuer 的帖子

got it

那么我这里发送方没有粘包可能会是什么原因呢?

论坛徽章:
0
发表于 2010-01-11 21:34 |显示全部楼层
原帖由 xpl 于 2010-1-11 18:06 发表
got it

那么我这里发送方没有粘包可能会是什么原因呢?

呵呵  我也只是知道点皮毛...  具体你可能要去专研协议去了,不过这应该不是一般人能做到的

不过你也可以自己实现个简单的啊...连续几次包都很小,你自己粘包嘛

论坛徽章:
0
发表于 2010-01-11 21:38 |显示全部楼层
http://net.chinaunix.net/8/2008/08/28/1257566.shtml

我觉得粘包的情况抓包是抓不出来的。
因为抓包软件都是一个一个skb为单位的。如果抓包能抓到粘包的情况,显然是发送包进行了粘包发送。

发送方没有粘包有可能tcp有push标志位。

还有能否粘包与协议栈发包算法关系很大。我觉得linux协议栈不太可能粘包吧。至少转发的包应该不会粘包。

从应用程序外发的包也许有可能粘包。

论坛徽章:
0
发表于 2010-01-11 23:23 |显示全部楼层
原帖由 emmoblin 于 2010-1-11 21:38 发表
http://net.chinaunix.net/8/2008/08/28/1257566.shtml

我觉得粘包的情况抓包是抓不出来的。
因为抓包软件都是一个一个skb为单位的。如果抓包能抓到粘包的情况,显然是发送包进行了粘包发送。

发送方没有 ...

那是两边 socket 的工作,是上层 TCP 栈要做的事情,与 NAT 无关,NAT 只负责地址转换,不负责处理 TCP 栈的高层应用
另外抓包软件也不是一个一个 skb 为单位的,是以 frame 为单位,skb 最大可以存储 65535 的 IP 数据报文,但抓包软件抓到的却是 frame(分片过的)
所谓的 “粘包” 好像是 TCP 栈中很基础的东西吧?怎么会不支持呢?BSD 栈都支持,Linux 栈从 BSD 栈发展而来,不支持吗?
建议看一下《TCP/IP 详解》卷一,第 19 章第 4 节 “Nagle 算法”

论坛徽章:
0
发表于 2010-01-12 10:21 |显示全部楼层
粘包应该是正常的tcp协议栈都支持的
现找了下Linux内核代码,大约在tcp_sendmsg函数中
有一段判断前一个skb末尾是否还有空间,有的话就把新的信息拷贝到上一个skb末尾,
否则新分配skb容纳新的数据
感觉这一块可能跟粘包有关,lz参考

论坛徽章:
0
发表于 2010-01-12 12:14 |显示全部楼层
多谢几位了

我再研究研究吧
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP