TCP粘包这个概念,我听过许多次,但是查了又查,似乎也没有人知道这个概念的来源,而且这件事“以讹传讹”弄出了很多的版本,比如我就听到过以下几种说法:
1. TCP“粘包”,这类说法相对靠谱一些,加了一个双引号,指出了TCP为提高传输效率,发送方往往要收集到足够多的数据后才发送一包数据。真实的TCP数据包之间是不会粘连的,发生粘连的仅仅是“逻辑包”。也就是client端每次通过socket send的数据。代表性的解决方案有VC知识库上的这篇文章,认真的分析了接收端的拆“包”协议:点击打开链接。
2. 正常情况下不会粘包,只有在网络发生拥塞的时候才会粘包。
3. 是否处理“粘包”是区分TCP新手和老鸟的重要区别,除了要考虑粘包,还要考虑丢包......
对于第2条和第3条,我不知道该说什么好了。至于第1条,解决的策略是对的,但是这个问题的定义有误,TCP/IP协议本身就是一个流协议,关于这个问 题,Effective TCP/IPProgramming一书的tip 6 RememberThat TCP Is a Stream Protocol对此有生动的阐释。
假设Host A通过socket连接向Host B发送两条消息Message M1和Message M2,那么两条消息的打包方式可能有以下四种:
这也是所谓的“粘包”问题的根源,TCP协议的打包方式,该书中有一句精彩评论:
按作者的观点,在TCP协议中提"packet”都不准确,更别提所谓的“粘包”了。再说3当中的丢包问题,是对TCP协议的理解错误,TCP协议保证了丢包的重传机制,而且不会打乱包与包之间的顺序,请看下面这段话:
也就是说问题是实实在在存在的,但是“粘包”这个提法不准确。应用到TCP协议的应用程序,都应该对TCP的流协议本质具有充分的认识,不能依赖于特定的TCP打包方式(比如客户端的一条消息打一个包),解决方案在我推荐的书中找,核心思想是在每个逻辑包头加上逻辑包的长度。