Netty笔记(六)之netty中的解码器

2022-09-17 13:15:33

netty版本

  1. netty版本:io.netty:netty-all:4.1.33.Final

netty 内置解码器

LineBasedFrameDecoder

  1. 基于行分隔的解码器LineBasedFrameDecoder是一个特殊的分隔符解码器,该解码器使用的分隔符为:windows的r\n和类linux的\n

  2. 成员变量,前三个变量可由用户根据实际情况配置,后两个变量解码时使用。

    // 最大帧长度,超过此长度将抛出异常TooLongFrameExceptionprivatefinalint maxLength;// 是否快速失败,true-检测到帧长度过长立即抛出异常不在读取整个帧// false-检测到帧长度过长依然读完整个帧再抛出异常privatefinalboolean failFast;// 是否略过分隔符,true-解码结果不含分隔符privatefinalboolean stripDelimiter;// 超过最大帧长度是否丢弃字节privateboolean discarding;privateint discardedBytes;// 丢弃的字节数

DelimiterBasedFrameDecoder

  1. DelimiterBasedFrameDecoder解码器是更通用的分隔符解码器,可支持多个分隔符,每个分隔符可为一个或多个字符。如果定义了多个分隔符,并且可解码出多个消息帧,则选择产生最小帧长的结果

    +--------------+| ABC\nDEF\r\n|+--------------+
        可有两种结果+-----+-----++----------+| ABC| DEF|()| ABC\nDEF|(×)+-----+-----++----------+
  2. 该编码器可配置的变量与LineBasedFrameDecoder类似,只是多了一个ByteBuf[] delimiters用于配置具体的分隔符。

  3. Netty在Delimiters类中定义了两种默认的分隔符,分别是NULL分隔符和行分隔符:

    publicstatic ByteBuf[]nulDelimiter(){returnnewByteBuf[]{
                    Unpooled.wrappedBuffer(newbyte[]{0})};}publicstatic ByteBuf[]lineDelimiter(){returnnewByteBuf[]{
                    Unpooled.wrappedBuffer(newbyte[]{'\r','\n'}),
                    Unpooled.wrappedBuffer(newbyte[]{'\n'}),};}

FixedLengthFrameDecoder

  1. 按照固定长度frameLength解码出消息帧

  2. 如下的数据帧解码为固定长度3的消息帧示例如下:

    +---+----+------+----++-----+-----+-----+| A| BC| DEFG| HI|->| ABC| DEF| GHI|+---+----+------+----++-----+-----+-----+
  3. 解码方法

    protected Objectdecode(ChannelHandlerContext ctx, ByteBuf in)throws Exception{if(in.readableBytes()< frameLength){return null;}else{return in.readSlice(frameLength).retain();}}

LengthFieldBasedFrameDecoder

  1. 基于长度字段的消息帧解码器,该解码器可根据数据包中的长度字段动态的解码出消息帧。一个推荐的二进制传输协议可设计为如下格式:

    +----------+------+----------+------+|  头部长度|  头部|  数据长度| 数据|+----------+------+----------+------+
  2. 成员变量

    //长度字段的字节序:大端或小端,默认为大端privatefinal ByteOrder byteOrder;//maxFrameLength和failFast与其他解码器相同,控制最大帧长度和快速失败抛异常privatefinalint maxFrameLength;//该解码器failFast默认为trueprivatefinalboolean failFast;//表示长度字段偏移量即在一个数据包中长度字段的具体下标位置。标准情况,该长度字段为数据部分长度privatefinalint lengthFieldOffset;//表示长度字段的具体字节数,如一个int占4字节。该解码器支持的字节数有:1,2,3,4和8,其他则会抛出异常。另外,还需要注意的是:长度字段的结果为无符号数。privatefinalint lengthFieldLength;//是一个长度调节量,当数据包的长度字段不是数据部分长度而是总长度时,可将此值设定为头部长度,便能正确解码出包含整个数据包的结果消息帧。注意:某些情况下,该值可设定为负数。privatefinalint lengthAdjustment;//表示需要略过的字节数,如果我们只关心数据部分而不关心头部,可将此值设定为头部长度从而丢弃头部。privatefinalint initialBytesToStrip;
  3. 构造法方法

    publicLengthFieldBasedFrameDecoder(
                ByteOrder byteOrder,// ByteOrder.BIG_ENDIAN 默认大端字节int maxFrameLength,int lengthFieldOffset,int lengthFieldLength,int lengthAdjustment,int initialBytesToStrip,boolean failFast//默认true)

LengthFieldBasedFrameDecoder案例

需求1

  1. 如下待解码数据包,正确解码为消息帧,其中长度字段在最前面的2字节,数据部分为12字节的字符串"HELLO, WORLD",长度字段0x000C=12表示数据部分长度,数据包总长度则为14字节。

       解码前(14 bytes)                 解码后(14 bytes)+--------+----------------++--------+----------------+| Length| Actual Content|----->| Length| Actual Content||0x000C|"HELLO, WORLD"||0x000C|"HELLO, WORLD"|+--------+----------------++--------+----------------+
  2. 构造传参

    publicLengthFieldBasedFrameDecoder(int maxFrameLength,1024int lengthFieldOffset,0int lengthFieldLength,2int lengthAdjustment,0int initialBytesToStrip0)

需求2

  1. 消息帧中去除长度字段。

    	 解码前(14 bytes)                 解码后(12 bytes)+--------+----------------++----------------+| Length| Actual Content|----->| Actual Content||0x000C|"HELLO, WORLD"||"HELLO, WORLD"|+--------+----------------++----------------+
  2. 构造传参

    publicLengthFieldBasedFrameDecoder(int maxFrameLength,1024int lengthFieldOffset,0int lengthFieldLength,2int lengthAdjustment,0int initialBytesToStrip2)

需求3

  1. 需求1数据包中长度字段表示数据包总长度。

    	 解码前(14 bytes)                 解码后(14 bytes)+--------+----------------++--------+----------------+| Length| Actual Content|----->| Length| Actual Content||0x000E|"HELLO, WORLD"||0x000E|"HELLO, WORLD"|+--------+----------------++--------+----------------+
  2. 构造传参

    publicLengthFieldBasedFrameDecoder(int maxFrameLength,1024int lengthFieldOffset,0int lengthFieldLength,2int lengthAdjustment,-2;// 调整长度字段的2字节int initialBytesToStrip2)

需求4

  1. 数据包有两个头部HDR1和HDR2,长度字段以及数据部分组成,其中长度字段值表示数据包总长度。结果消息帧需要第二个头部HDR2和数据部分。请先给出答案再与标准答案比较,结果正确说明你已完全掌握了该解码器的使用。

    	       解码前(16 bytes)                  解码后(13 bytes)+------+--------+------+----------------++------+---------------+| HDR1| Length| HDR2| Actual Content|-->| HDR2| Actual Content||0xCA|0x0010|0xFE|"HELLO, WORLD"||0xFE|"HELLO, WORLD"|+------+--------+------+----------------++------+---------------+
  2. 构造传参

    publicLengthFieldBasedFrameDecoder(int maxFrameLength,1024int lengthFieldOffset,1int lengthFieldLength,2int lengthAdjustment,-3int initialBytesToStrip3)
  • 作者:jannals
  • 原文链接:https://blog.csdn.net/usagoole/article/details/87389182
    更新时间:2022-09-17 13:15:33