跳到主要内容

四、Netty 教程 – Netty粘包_拆包解决之道

作者:唐亚峰 | 出自:唐亚峰博客

> TCP是个协议,是一串没有界限的数据,TCP底层并不了解上层业务数据的含义,它会根据TCP缓冲区实际情况进行包的划分,在上一篇文章中介绍了什么是Netty,本章介绍Netty粘包和拆包…

粘包和拆包

学过TCP的都知道,它是属于传输层的协议,传输层除了有TCP协议外还有UDP协议,但是UDP是不存在拆包和粘包的。UDP是基于报文发送的,从UDP的帧结构可以看出,在UDP首部采用了16bit来指示UDP数据报文的长度,因此在应用层能很好的将不同的数据报文区分开,从而避免粘包和拆包的问题。

TCP是基于字节流的,虽然应用层和TCP传输层之间的数据交互是大小不等的数据块,但是TCP把这些数据块仅仅看成一连串无结构的字节流,没有边界;另外从TCP的帧结构也可以看出,在TCP的首部没有表示数据长度的字段,基于上面两点,在使用TCP传输数据时,才有粘包或者拆包现象发生的可能。

 

  • 服务端分两次读取到了两个独立的数据包,分别是D1和D2没有粘包和拆包
  • 服务端一次接受到两个粘在一起的数据包,D2和D1,被称为TCP粘包服务端分两次读取到了两个数据包,第一次读取到完整的D1,D2部分内容,第二次读取了D2的剩余内容,这被称之为TCP拆包操作
  • 服务端分两次读取到了两个数据包,第一次读取到了D1_1,第二次读取到了D1包的剩余内容和完整的D2数据包
  • 如果此时服务端TCP接收滑窗非常小,而数据包内容相对较大的情况,很可能发生服务端多次拆包才能将D1和D2数据接收完整

产生原因

  • 要发送的数据大于TCP发送缓冲区剩余空间大小,将会发生拆包。
  • 待发送数据大于MSS(最大报文长度),TCP在传输前将进行拆包。
  • 要发送的数据小于TCP发送缓冲区的大小,TCP将多次写入缓冲区的数据一次发送出去,将会发生粘包。