TCP粘包问题 及 解决

什么是粘包

如果客户端连续不断地向服务端发送数据包时,服务端接受的数据会出现两个数据包粘在一起的情况。

  • TCP是基于字节流的,虽然应用层和TCP传输之间的数据交互是大小不等的数据块,但是TCP认为这些数据块仅仅是一串无结构的字节流,没有边界。
  • 从TCP结构的帧可以看到,在TCP的首部是没有表示数据长度的字段。

基于上面两点,在使用TCP传输时,才有粘包或者拆包的现象的发生。

一个数据包中包含了两个发送端发送的数据包信息,这种现象即为粘包。

接收端收到了两个数据包,但是这两个数据包要么不完整,要么多出来一块,这种情况即发生了粘包和拆包。

拆包和粘包的问题导致接收端在处理的时候会非常困难,因为无法区分一个完整的数据包。

TCP粘包是怎么产生的

  1. 发送方产生粘包

采用 TCP 协议传输数据的客户端与服务器经常是保持一个长连接的状态(一次连接发一次数据不存在粘包),双方在连接不断开的情况下,可以一直传输数据。

但当发送的数据包过于小时,那么 TCP 协议默认的会启用 Nagle 算法,将这些较小的数据包进行合并发送(缓冲区数据发送是一个堆压的过程);这个合并过程就是在发送缓冲区中进行的,也就是说数据发送出来它已经是粘包的状态了。

  1. 接收方产生粘包

接收方采用 TCP 协议接收数据时的过程是这样的:数据到接收方,从网络模型的下方传递至传输层,传输层的 TCP 协议处理是将其放置接收缓冲区,然后由应用层来主动获取(C 语言用 recv、read 等函数);

这时会出现一个问题,就是我们在程序中调用的读取数据函数不能及时的把缓冲区中的数据拿出来,而下一个数据又到来并有一部分放入的缓冲区末尾,等我们读取数据时就是一个粘包。(放数据的速度 > 应用层拿数据速度)

怎么解决拆包和粘包

分包机制一般有两个通用的解决方法:

  1. 特殊字符控制;
  2. 在包头首部添加数据包的长度。

如果使用 netty 的话,就有专门的编码器和解码器解决拆包和粘包问题了。

tips:UDP 没有粘包问题,但是有丢包和乱序。不完整的包是不会有的,收到的都是完全正确的包。传送的数据单位协议是 UDP 报文或用户数据报,发送的时候既不合并,也不拆分。

UDP是否会出现粘包

对于UDP, 如果还没有上层交付数据, UDP的报文长度仍然在. 同时, UDP是一个一个把数据交付给应用层. 就有很明确的数据边界.

站在应用层的站在应用层的角度, 使用UDP的时候, 要么收到完整的UDP报文, 要么不收. 不会出现"半个"的情况。

©️2020 CSDN 皮肤主题: 1024 设计师:上身试试 返回首页