https://blog.youkuaiyun.com/zhangxinrun/article/details/6721495
https://blog.youkuaiyun.com/weixin_41047704/article/details/85340311
什么是粘包
假设发送方应用层需要发送两个数据data1和data2,在接收端有以下几种情况:
A. 先接收到data1,再接收到data2;
B. 现接受到data1的部分数据,然后收到data1的剩余部分和data2的全部数据;
C. 先接收到data1的全部和data2的部分,再接收到data2的剩余部分;
D. 一次收到data1和data2的全部数据。
- B、C、D就是所说的粘包现象;
- 粘包会出现在TCP中,因为TCP是基于“流”的协议,也就是没有界限的一串数据,TCP中的一个数据段可能会包含应用层的多个数据报文。
- 粘包问题不会在UDP中发生,因为UDP是面向报文传输的,应用层给UDP多大的报文,UDP就照样发送(一次性发送);若UDP报文太长,那么将会在网络层进行分片;若UDP报文太短,那么会浪费资源。
- 举例说明:有三个数据报文,大小分别为2k、4k、6k,如果采用UDP发送的话,不管接受方的接收缓存有多大,我们必须要进行至少三次以上的发送才能把数据包发送完,但是使用TCP协议发送的话,我们只需要接受方的接收缓存比12k大,就可以一次把这3个数据包全部发送完毕。
粘包出现的原因
也就是出现BCD现象的原因如下:
发送方原因
- TCP发送方默认采用Nagle算法(作用是减少网络中TCP数据段的数量),而Nagle算法主要完成的工作是:当我们提交一段数据给TCP发送时,TCP并不立刻发送此段数据,而是等待一小段时间,看看在等待期间是否还有要发送的数据,若有则会一次把这两段数据发送出去;
- Nagle算法可能导致C、D的发生(Nagle算法不会将data1拆成两半,即不会导致B)。
接收方原因
- TCP会把接收到的数据放到自己的缓存区(注意不是窗口)中,然后通知应用来拿,如果应用层因为某些原因取数据不及时,就可能造成多个数据被缓存,应用程序就会读取到多个首尾相连的、粘到一起的数据。
粘包的解决
1.什么时候需要解决粘包问题
- data1和data2不是同一块数据的不同部分时;
- 若data1和data2是同一块数据的不同部分,不需要解决粘包,例如一个文件拆成多个部分进行发送,而data1和data2正好是这个文件的连续两段,就不需要解决粘包问题。
2.粘包的解决方法——发送方
- 关闭Nagle算法,使用TCP_NODELAY选项来关闭算法;
2.粘包的解决方法——接收方
- 没有解决办法。
2.粘包的解决方法——接收方应用层
- 格式化数据:每条数据有固定的格式(开始符+数据+结束符),这种方法需要注意选择开始复和结束符时要确保数据内部不包含开始符和结束符;
- 发送长度:发送每条数据时,将数据的长度一并发送,例如规定数据前4位时数据的长度,应用层就可以根据长度判断每个分组的开始和结束位置。