netty学习笔记一:TCP粘包拆包

什么是TCP拆包粘包

假设客户端发送了2条消息M1,M2。可能会出现以下几种情况。

1、服务端正常接收到M1,M2这两条消息。

2、服务端一次接收到了2个数据包,M1和M2粘合在一起,这时候就被称为TCP粘包。

3、服务端分两次读取到了两个数据包,第一次读取到M1包整包和M2包部分内容M2_1,第二次读取到了M2剩余的内容M2_2,这时候被称为TCP拆包。

4、服务端分两次读取到了两个数据包,第一次读取到M1包的部分内容M1_1,第二次读取到了M1剩余的内容M1_2和M2整包,这时候也是发生了TCP拆包。

5、当服务端TCP接收滑窗非常小,或者M1、M2数据包比较大时,服务端需要将M1,M2进行多次拆包才能接收完全,这时候也是发生了TCP拆包。

同时,我们需要明确的是,其实在TCP层面上它是没有拆包粘包概念的。因为TCP只是负责传输上层协议所提供的数据,它本身并不知道这些数据的关系,只是像流一样将这些数据传输过去。因此,这个拆包粘包概念更准确来说是相对于应用层数据划分的。

拆包粘包产生原因

粘包可能的产生原因

  1、原本没有粘包进行TCP传输的数据包,在read操作调用不及时去读取缓冲区数据的情况下,很可能会发生粘包;

  2、应用程序写入数据大小小于缓冲区大小,网卡会将应用多次写入的数据发送到网络上,这将会发生粘包。

拆包可能的产生原因

1、应用程序写入的数据比缓冲区还大时,数据不能一次性发送,将发生拆包。

2、TCP进行分段时数据大小大于MSS大小的时候将发生拆包。

3、以太网帧的payload数据大于MTU大小时发生拆包。

 

注:MTU和MSS的概念如下。

MTU:代表TCP/IP协议传输数据报时的最大传输单元。以太网协议规定最大帧长度是1500Byte(不包括报文头部)。

MSS: MSS是TCP专属概念,TCP在三次握手建立连接过程中,会在SYN报文中使用MSS(Maximum Segment Size)选项功能,协商交互双方能够接收的最大段长MSS值。其标识TCP能够承载的最大的应用数据段长度。

MSS=MTU-20字节TCP报头-20字节IP报头。在IPv4网络中,一般情况下,MSS=1460=1500-20-20。 在IPv6网络中,一般情况下,MSS=1440=1500-20-40。

 常见解决策略

1、消息定长。例如每个报文的大小固定为200字节,不够则空格补齐;

2、在包尾增加回车换行符进行分割,如FTP协议;

3、将消息分成消息头和消息体,消息头中包含表示消息()总长度的字段。如下示例,length字段代表本条消息的长度大小。

 +————+—————————+ 

  | Length   | Actual Content          |

  | 0x000C  | "HELLO, WORLD"   |

 +————+—————+———-+ 

 Netty常见解决类

1、LineBasedFrameDecoder:基于行来进行消息粘包拆包处理的。

2、DelimiterBaseFrameDecoder:基于分隔符做结束标志进行粘包拆包处理的,对于使用" "," "做分隔符内部会调用LineBasedFrameDecoder来做统一的行分割。

3、FixedLengthFrameDecoder:基于固定长度消息进行粘包拆包处理的。

4、LengthFieldBasedFrameDecoder:基于消息头指定消息长度进行粘包拆包处理的。

原文地址:https://www.cnblogs.com/magotzis/p/9527024.html