是一个根据在接收到的 ByteBuf 消息中的长度值对这个消息动态的切分的解码器。在需要解码二进制消息并且在消息头中包含代表这条消息的整体长度或消息体长度的字段的情况下非常有用。
A decoder that splits the received {@link ByteBuf}s dynamically by the value of the length field in the message. It is particularly useful when you decode a binary message which has an integer header field that represents the length of the message body or the whole message.
这个类拥有许多配置参数,所以它可以用来解析任何包含长度字段的消息,包含长度字段的消息在自定义的客户端-服务端协议之间非常常见。常用的配置参数有:
ByteOrder byteOrder : 这个二进制消息是大端模式[默认]/小端模式
int maxFrameLength : 这个二进制消息最大长度
int lengthFieldOffset : 这个二进制消息长度的字段位于消息的偏移位置
int lengthFieldLength : 这个二进制消息长度的字段的字节长度
int lengthAdjustment: 长度调整,添加到长度字段数值的补偿值,一般用于长度字段代表整个消息长度
int initialBytesToStrip :跳过指定长度字节,一般用于跳过消息头,只将消息体保留
boolean failFast :快速失败,当消息的长度超过maxFrameLength时立即抛出TooLongFrameException异常
下面一些例子,可以让你对参数的作用有一个基本的了解。
1、2个bytes长度字段,偏移为0,不要跳过消息头
自定义消息解析前 (14 bytes)
+--------+----------------+
| 长度字段| 真实内容 |
| 0x000C | "HELLO, WORLD" |
+--------+----------------+
可以看出消息的长度字段数值是12,代表真实内容的字节数。默认情况下,这个解码器假定长度字段表示长度字段后面的字节数。因此,可以用简单的参数组合进行解码。
lengthFieldOffset = 0 (这个二进制消息长度的字段位于消息的最开始,故偏移量为0)
lengthFieldLength = 2 (如题,2个bytes长度字段)
lengthAdjustment = 0 (长度字段即代表后面的数据长度,12 -12 = 0无需长度调整)
initialBytesToStrip = 0 ( 不跳过消息头,保留完整消息)这个字段根据需要进行设定
自定义消息解析前 (14 bytes) 自定义消息解析后 (14 bytes)
+--------+----------------+ +--------+----------------+
| Length | Actual Content |----->| Length | Actual Content |
| 0x000C | "HELLO, WORLD" | | 0x000C | "HELLO, WORLD" |
+--------+----------------+ +--------+----------------+
2、2个bytes长度字段,偏移为0,跳过消息头
还是上面的消息,因为可以通过ByteBuf#readableBytes()获取数据长度,所以可以通过initialBytesToStrip跳过长度字段(或者整个消息头)。
lengthFieldOffset = 0 (这个二进制消息长度的字段位于消息的最开始,故偏移量为0)
lengthFieldLength = 2 (如题,2个bytes长度字段)
lengthAdjustment = 0 (长度字段 后面数据长度12,长度数值12,长度调整 12 - 12 = 0)
initialBytesToStrip = 2( 跳过消息头,仅保留消息体)这个字段根据需要进行设定
解析前 (14 bytes) 解析后 (12 bytes)
+--------+----------------+ +----------------+
| Length | Actual Content |----->| Actual Content |
| 0x000C | "HELLO, WORLD" | | "HELLO, WORLD" |
+--------+----------------+ +----------------+
3、2个bytes长度字段,偏移为0,不要跳过消息头,长度字段代表整个消息长度
BEFORE DECODE (14 bytes)
+--------+----------------+
| Length | Actual Content |
| 0x000E | "HELLO, WORLD" |
+--------+----------------+
lengthFieldOffset = 0 (这个二进制消息长度的字段位于消息的最开始,故偏移量为0)
lengthFieldLength = 2 ((如题,2个bytes长度字段)
lengthAdjustment = -2 (长度字段 后面数据长度12,长度数值14[0x000E],长度调整 12 - 14 = -2)
initialBytesToStrip = 0 ( 不跳过消息头,保留完整消息)这个字段根据需要进行设定
BEFORE DECODE (14 bytes) AFTER DECODE (14 bytes)
+--------+----------------+ +--------+----------------+
| Length | Actual Content |----->| Length | Actual Content |
| 0x000E | "HELLO, WORLD" | | 0x000E | "HELLO, WORLD" |
+--------+----------------+ +--------+----------------+
4、5bytes消息头中后3bytes为长度字段,不跳过消息头
BEFORE DECODE (17 bytes)
+----------+----------+----------------+
| Header 1 | Length | Actual Content |
| 0xCAFE | 0x00000C | "HELLO, WORLD" |
+----------+----------+----------------+
lengthFieldOffset = 2 (这个二进制消息长度的字段位于消息的第三个字节,故偏移量为Header1 的字节数2)
lengthFieldLength = 3 (如题,5bytes中后3bytes为长度字段)
lengthAdjustment =0 (长度字段 后面数据长度12,长度数值12[0x000C],长度调整 12 - 12 = 0)
initialBytesToStrip = 0 ( 不跳过消息头,保留完整消息)这个字段根据需要进行设定
5、5bytes消息头中前3bytes为长度字段,不跳过消息头
BEFORE DECODE (17 bytes)
+----------+----------+----------------+
| Length | Header 1 | Actual Content |
| 0x00000C | 0xCAFE | "HELLO, WORLD" |
+----------+----------+----------------+
lengthFieldOffset = 0 (这个二进制消息长度的字段位于消息的最开始,故偏移量为0)
lengthFieldLength = 3 (如题,5bytes中后3bytes为长度字段)
lengthAdjustment =2 (长度字段 后面数据长度14,长度数值12[0x000C],长度调整 14 - 12 = 2)
initialBytesToStrip = 0 ( 不跳过消息头,保留完整消息)这个字段根据需要进行设定
6、2字节长度在4字节消息头中偏移为1字节,跳过消息头中第一个字段和长度字段
BEFORE DECODE (16 bytes)
+------+--------+------+----------------+
| HDR1 | Length | HDR2 | Actual Content |
| 0xCA | 0x000C | 0xFE | "HELLO, WORLD" |
+------+--------+------+----------------+
lengthFieldOffset = 1 (这个二进制消息长度的字段位于消息的第1个字段HDR1之后,故偏移量为HDR1的字节数1)
lengthFieldLength = 2 (如题,2bytes为长度字段)
lengthAdjustment =1 (长度字段 后面数据长度13,长度数值12[0x000C],长度调整 13 - 12 = 1)
initialBytesToStrip = 3 ( 跳过消息头中第一个字段和长度字段,Len(HDR1)+Len(Length) -> 1+2)这个字段根据需要进行设定
7、2字节长度在4字节消息头中偏移为1字节,跳过消息头中第一个字段和长度字段,长度字段值代表整个消息长度
BEFORE DECODE (16 bytes)
+------+--------+------+----------------+
| HDR1 | Length | HDR2 | Actual Content |
| 0xCA | 0x0010 | 0xFE | "HELLO, WORLD" |
+------+--------+------+----------------+
lengthFieldOffset = 1 (这个二进制消息长度的字段位于消息的第1个字段HDR1之后,故偏移量为HDR1的字节数1)
lengthFieldLength = 2 (如题,2bytes为长度字段)
lengthAdjustment = -3 (长度字段 后面数据长度13 [Len(HDR2)+Len(Actual Content)],长度数值16 [0x0010],长度调整 13 - 16 = -3)
initialBytesToStrip = 3 ( 跳过消息头中第一个字段和长度字段,Len(HDR1)+Len(Length) -> 1+2)这个字段根据需要进行设定