TCP粘包和拆包 作者:马育民 • 2018-12-26 10:37 • 阅读:10170 # TCP粘包 ### 什么是粘包? 发送端发送的若干个数据包,到接收端接收时,粘成一个数据包,从接收缓冲区看,后一包数据的头紧接着前一包数据的尾。 ### TCP和UDP哪个会发生粘包? - TCP协议编程时会发生粘包。 TCP协议是面向连接的,**基于字节流传输数据**。所谓字节流,可以想象河里的流水,是连成一片的,也就是没有界限的一串字节数据,数据是 **没有分界线** 的 - UDP是基于数据报的协议,不会出现粘包 ### 发生粘包的原因 原因有2个,一个是发送时粘包,一个是接收时粘包 ### 1.发送端粘包 **一句话解释**:发送时使用Nagle算法,将多个间隔较小且数据量小的数据包,合并成一个大数据包并将其发送 **详细解释:** 为了提高性能,在发送端有 **数据缓冲区**,用来存放要发送的数据,发送端为了将多个包,**更有效** 的发到接收端,使用了优化方法----**Nagle算法**,该算法将多次间隔较小且数据量小的数据,合并成一个大的数据块,发送给接收端。 相当于:搬运工一次搬运一瓶啤酒,效率低下,将6瓶啤酒包装成一箱,一次搬运一箱,效率高,但接收端接收的是一箱啤酒,接收端不知道应该拆分出来 [](http://www.malaoshi.top/upload/0/0/1EF2UoQEmJQy.png) ### 2.接收端粘包 **一句话解释**:应用程序不及时接收缓冲区的包,造成多个包接收 **详细解释:** 为了提高性能,在接收端有 **数据缓冲区**,用来存放接收的数据,然后应用程序从缓冲区里读取数据。如果接收的速度大于应用程序读取的速度,**多个数据包** 就会存放到缓冲区里,由于TCP协议是 **基于流的传输**,数据没有边界,应用程序读取时,就会读到多个首尾相接粘到一起的包。 [](http://www.malaoshi.top/upload/0/0/1EF2UrbJQvXp.png) # TCP拆包 ### 什么是拆包? 发送端发送一个数据包,到接收端接收时,接收端通过多次接收才得到完整的数据包 ### TCP和UDP哪个会发生拆包? - TCP协议编程时会发生拆包。 TCP协议是面向连接的,**基于流的传输**。所谓流,可以想象河里的流水,是连成一片的,也就是没有界限的一串数据,数据是 **没有分界线** 的 - UDP是基于数据报的协议,不会出现拆包 ### 发生拆包的原因 1. 应用程序发送的数据大于缓冲区大小,当缓冲区已满时,将数据拆分直接发送了 [](http://www.malaoshi.top/upload/0/0/1EF2VHGzJLqW.png) 2. 应用程序发送数据大于MSS是将发生拆包 当TCP报文长度-TCP头部长度>[MSS](http://www.malaoshi.top/show_1EF2VK9VXVdc.html "MSS")的时候 [](http://www.malaoshi.top/upload/0/0/1EF2VKcEWEst.png) ## 什么情况不需要考虑粘包/拆包 1. 短链接,且只有一种数据结构,类似于http协议,就是建立连接,然后发送/接收字符串,然后断开连接,不需要考虑粘包/拆包 2. 发送数据无结构,如文件传输,发送端只管发送,接收端只管接收数据,不需要考虑粘包/拆包 # 什么情况必须考虑粘包/拆包 发送不同结构的数据,必须考虑粘包/拆包。接收方将不同结构的数据拼到一起,那么接收方无法识别 # 解决粘包/拆包 TCP是基于字节流传输数据的,且协议本身无法避免粘包,拆包的发生,那我们只能在应用层数据协议上,加以控制 1. 消息定长,比如每次发送数据的长度固定为100个字节,如果不够长度用空格补充。那么接收端每接收100个字节的数据,就认为是一个完整的数据包 2. 在消息的尾部加一些特殊字符(比如换行符),那么在读取数据的时候,只要读到这个特殊字符,就认为是一个完整的数据包了 3. 将消息分为消息头和消息体,消息头长度固定,而且包含消息总长度(或者消息体长度),接收端读取消息头后,根据长度信息,读取数据(类似TLV格式) 4. 更复杂的应用层协议。 感谢下面文章: https://www.cnblogs.com/qiaoconglovelife/p/5733247.html https://www.cnblogs.com/1987-05-04/p/6727922.html https://blog.csdn.net/gengbaolong/article/details/75450208 https://blog.csdn.net/qq513036862/article/details/53640317 https://zgc168.iteye.com/blog/1880620 https://www.cnblogs.com/kex1n/p/6502002.html 原文出处:http://www.malaoshi.top/show_1EF2UqhwMPPZ.html