TCP粘包和拆包

TCP粘包

什么是粘包?

发送端发送的若干个数据包,到接收端接收时,粘成一个数据包,从接收缓冲区看,后一包数据的头紧接着前一包数据的尾。

TCP和UDP哪个会发生粘包?

  • TCP协议编程时会发生粘包。
    TCP协议是面向连接的,基于字节流传输数据。所谓字节流,可以想象河里的流水,是连成一片的,也就是没有界限的一串字节数据,数据是 没有分界线 的

  • UDP是基于数据报的协议,不会出现粘包

发生粘包的原因

原因有2个,一个是发送时粘包,一个是接收时粘包

1.发送端粘包

一句话解释:发送时使用Nagle算法,将多个间隔较小且数据量小的数据包,合并成一个大数据包并将其发送

详细解释:
为了提高性能,在发送端有 数据缓冲区,用来存放要发送的数据,发送端为了将多个包,更有效 的发到接收端,使用了优化方法——Nagle算法,该算法将多次间隔较小且数据量小的数据,合并成一个大的数据块,发送给接收端。

相当于:搬运工一次搬运一瓶啤酒,效率低下,将6瓶啤酒包装成一箱,一次搬运一箱,效率高,但接收端接收的是一箱啤酒,接收端不知道应该拆分出来

2.接收端粘包

一句话解释:应用程序不及时接收缓冲区的包,造成多个包接收

详细解释:
为了提高性能,在接收端有 数据缓冲区,用来存放接收的数据,然后应用程序从缓冲区里读取数据。如果接收的速度大于应用程序读取的速度,多个数据包 就会存放到缓冲区里,由于TCP协议是 基于流的传输,数据没有边界,应用程序读取时,就会读到多个首尾相接粘到一起的包。

TCP拆包

什么是拆包?

发送端发送一个数据包,到接收端接收时,接收端通过多次接收才得到完整的数据包

TCP和UDP哪个会发生拆包?

  • TCP协议编程时会发生拆包。
    TCP协议是面向连接的,基于流的传输。所谓流,可以想象河里的流水,是连成一片的,也就是没有界限的一串数据,数据是 没有分界线 的

  • UDP是基于数据报的协议,不会出现拆包

发生拆包的原因

  1. 应用程序发送的数据大于缓冲区大小,当缓冲区已满时,将数据拆分直接发送了

  2. 应用程序发送数据大于MSS是将发生拆包
    当TCP报文长度-TCP头部长度>MSS的时候

什么情况不需要考虑粘包/拆包

  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


原文出处:/show_1EF2UqhwMPPZ.html