Netty TCP 粘包 & 拆包

粘包/拆包

TCP 的一个数据包可能包含一个、多个或者不足一个应用层数据包,程序需要按照一整个应用包进行处理,这就会带来一个问题,TCP 的数据包不能直接拿来处理。

原因深究

socket 缓冲区:socket 通信时,收发两端在内核层都有一个缓冲区,send时,数据不会马上发送到对端,而是写入到send缓冲区,由内核在合适的时机将数据发送到对端;接受端原理相似。

MTU(Max Transfer Unit)最大传输单元:MTU是网络层概念,表示一个网络数据帧的最大值,当送的数据大于MTU时,网络层会对数据进行分割发送,这个过程叫做分片

MSS(Max Segment Size)最大分段大小:MSS 是TCP传输层的概念,与MTU类似表示TCP数据包的最大值。为了达到最佳的传输效能TCP协议在建立连接的时候通常要协商双方的MSS值,这个值TCP协议在实现的时候往往用MTU值代替(需要减去IP数据包包头的大小20Bytes和TCP数据段的包头20Bytes)所以往往MSS为1460。TCP根据MSS 将小数据包合并为一个大的数据包,或者将一个大的数据包分割成MSS大小的数据包进行发送,这个过程叫做分段TCP 通过 MSS 避免了 在网络层的分片

基于以上,粘包/拆包会发生在以下几种情况:

  1. 单次数据写操作超出了socket 缓冲区的大小,导致内核不得不将缓冲区中的数据发送出去;

  2. 对于TCP协议,针对MSS的数据分段;

  3. 以太网帧大于MTU时的TCP分片;

  4. 应用层数据包太小导致的数据合并;

解决方案

  1. 消息定长,比如规定一个数据包200bytes,不够的空格补齐,很明显这种方式扩展性很差;

  2. 采用固定的消息分隔符,通过分隔符将数据包拆解开;

  3. 数据协议,将数据包分为消息头和消息体,消息头中说明本消息的总长度;

  4. 其他应用层协议;

你可能感兴趣的:(Netty TCP 粘包 & 拆包)