天天看点

Netty源码(三):Netty的粘包问题ByteToMessageDecoder1. 产生粘包和半包的原因2. 问题一:Netty如何实现编码解码的3.问题二:LengthFieldBasedFrameDecoder编码器的实现

1. 产生粘包和半包的原因

粘包产生的原因:两个包小于缓存区的大小,传送数据会将两个包都放在缓冲区中一起发送,就会产生粘包的问题。

半包产生的原因:当某一个包的大于缓冲区的大小,会被发送多次,每次就收到的就是一个不完整的数据包。

常见的处理手段:

Netty源码(三):Netty的粘包问题ByteToMessageDecoder1. 产生粘包和半包的原因2. 问题一:Netty如何实现编码解码的3.问题二:LengthFieldBasedFrameDecoder编码器的实现

netty对不同粘包半包问题的支持类

Netty源码(三):Netty的粘包问题ByteToMessageDecoder1. 产生粘包和半包的原因2. 问题一:Netty如何实现编码解码的3.问题二:LengthFieldBasedFrameDecoder编码器的实现

2. 问题一:Netty如何实现编码解码的

查看

ByteToMessageDecoder

,该类是解码器的实现类,查看其中的

channelRead

方法

1.调用了

cumulator.cumulate()

方法来实现数据包的拼接的操作

2.

callDecode()

方法解析数据包

Netty源码(三):Netty的粘包问题ByteToMessageDecoder1. 产生粘包和半包的原因2. 问题一:Netty如何实现编码解码的3.问题二:LengthFieldBasedFrameDecoder编码器的实现

2.1 cumulator.cumulate()方法拼接数据包

跟进源码,发现他分为两步:

1.如果是第一个数据包,就直接返回该数据包

2.如果不是第一个数据包,就将最新的数据追加导员来已经接收的数据包内

Netty源码(三):Netty的粘包问题ByteToMessageDecoder1. 产生粘包和半包的原因2. 问题一:Netty如何实现编码解码的3.问题二:LengthFieldBasedFrameDecoder编码器的实现

2.2

callDecode()

方法解析数据包

核心实现方法,

decodeRemovalReentryProtection

就是

callDecode

中的核心步骤

Netty源码(三):Netty的粘包问题ByteToMessageDecoder1. 产生粘包和半包的原因2. 问题一:Netty如何实现编码解码的3.问题二:LengthFieldBasedFrameDecoder编码器的实现

跟进源码

decodeRemovalReentryProtection

的源码,其中核心方法是514行的

decode

方法,但是此方法是一个抽象方法,也就是说

ByteToMessageDecoder

只是一个模板类,具体的decode方法实现在子类中

Netty源码(三):Netty的粘包问题ByteToMessageDecoder1. 产生粘包和半包的原因2. 问题一:Netty如何实现编码解码的3.问题二:LengthFieldBasedFrameDecoder编码器的实现

于是我们查看

ByteToMessageDecoder

的一个子类

FixedLengthFrameDecoder

FixedLengthFrameDecoder

是固定长度的编码解码方式,如果数据不足会补充空格等数据,它的decode方法如下:

1.如果我们接受到的数据小于数据帧限制的长度,那么无法解析数据,直接返回null

2.否则调用

readRetainedSlice

方法进行解析,

readRetainedSlice

就是将

ByteBuf

切出

frameLength

长度的数据出来

Netty源码(三):Netty的粘包问题ByteToMessageDecoder1. 产生粘包和半包的原因2. 问题一:Netty如何实现编码解码的3.问题二:LengthFieldBasedFrameDecoder编码器的实现

总结:Netty提供了一个

ByteToMessageDecoder

模板类,数据包的拼接交给该类完成,但是数据包的解析

decode

是一个抽象方法,具体实现交给子类完成。

3.问题二:LengthFieldBasedFrameDecoder编码器的实现

核心就是其中的四个参数:

1.

lengthFieldOffset

// length字段的偏移量

2.l

engthFieldLength

// legnth字段所占的长度

3.

lengthAdjustment

// 可能我们除了实际内容字段以外,还额外增加2个字段的其他信息,lengthAdjustment=2,那么需要读取的数据就是length+2

4.

initialBytesToStrip

// 我们解析出来的数据是从第几位开始的,如果我们不需要接收length字段,那么initialBytesToStrip=2,解析出来就只有内容部分

Netty源码(三):Netty的粘包问题ByteToMessageDecoder1. 产生粘包和半包的原因2. 问题一:Netty如何实现编码解码的3.问题二:LengthFieldBasedFrameDecoder编码器的实现