接下来介绍netty如何切割分包

学习目的,了解处理业务,方便以后脱离依赖

读者如果不感兴趣或看不懂可以先忽略,难度比较大

LengthFieldBasedFrameDecoder.class

    public LengthFieldBasedFrameDecoder(
            ByteOrder byteOrder,     //大小端模式 默认大端 ByteOrder BIG_ENDIAN
            int maxFrameLength,      //包Frame netty叫帧概念 最大上限
            int lengthFieldOffset,     //包长度信息偏移多少bytes
            int lengthFieldLength,    //包长度单位为bytes
            int lengthAdjustment,     //包附加信息占多少位,如包尾部checksum 也可以不用设置
            int initialBytesToStrip,//忽悠包头信息,返给上层时会去掉这部份bytes
            boolean failFast)        //解包出错,控制抛异常,默认为true 无需关心这选项

如示例

int maxFrameLength = Short.MAX_VALUE;
int lengthFieldOffset =1;
int lengthFieldLength =2;
new LengthFieldBasedFrameDecoder(ByteOrder.BIG_ENDIAN,maxFrameLength,lengthFieldOffset,lengthFieldLength,0,0,true);

如图:

数据包由低到高是从左到右

红色部份lengthFieldOffset 1byte=8bits 

蓝色部份lengthFieldLength 2byte=16bits = short

粉色部份messageLength 2byte 读取 蓝色部份由于大端模式 高位 0000 0010 等于2 

[编织消息框架][设计协议]解决粘包半包(下)

 图2

消息长度为1byte 

[编织消息框架][设计协议]解决粘包半包(下)

解读netty源码

分四部份

1.netty解码介绍

2.边界判断

3.计算逻辑

4.切割包

第一部份

先看下LengthFieldBasedFrameDecoder继承类之间的关系

[编织消息框架][设计协议]解决粘包半包(下)

ByteToMessageDecoder处理比较复杂,先不考虑

其实解码只要工作方法是

protected Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception
//公开调用方法 out 是解码后保存返回,为什么是个数组?原因有可能出现粘包情况多次解码,合并结果一次返回上层业务
protected final void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
    //调用实现解码方法
    Object decoded = decode(ctx, in);
    if (decoded != null) {
        out.add(decoded);
    }
}

提示:如果自己实现解码 继承ByteToMessageDecoder类,逻辑写在decode(ChannelHandlerContext ctx, ByteBuf in)方法即可

第三部份

 1     //计算包长度偏移坐标 已读坐标+lengthFieldOffset参数
 2     int actualLengthFieldOffset = in.readerIndex() + lengthFieldOffset;
 3     //算出包长度
 4     long frameLength = getUnadjustedFrameLength(in, actualLengthFieldOffset, lengthFieldLength, byteOrder);
 5     
 6     //包实际长度  加上开始忽悠的 lengthFieldEndOffset参数 加上 lengthAdjustment 参数
 7     frameLength += lengthAdjustment + lengthFieldEndOffset;
 8     
 9     //跳过忽悠头部 initialBytesToStrip参数
10     in.skipBytes(initialBytesToStrip);
11         
12     //length 单位是byte 如2 是占一个short长度 4占int长度 8占long长度
13     protected long getUnadjustedFrameLength(ByteBuf buf, int offset, int length, ByteOrder order) {
14         //转换大小端模式
15         buf = buf.order(order);
16         long frameLength;
17         switch (length) {
18         case 1:
19             frameLength = buf.getUnsignedByte(offset);
20             break;
21         case 2:
22             frameLength = buf.getUnsignedShort(offset);
23             break;
24         case 3:
25             frameLength = buf.getUnsignedMedium(offset);
26             break;
27         case 4:
28             frameLength = buf.getUnsignedInt(offset);
29             break;
30         case 8:
31             frameLength = buf.getLong(offset);
32             break;
33         default:
34             throw new DecoderException(
35                     "unsupported lengthFieldLength: " + lengthFieldLength + " (expected: 1, 2, 3, 4, or 8)");
36         }
37         return frameLength;
38     }
计算逻辑

相关文章:

  • 2021-10-03
  • 2022-01-28
  • 2021-12-19
  • 2022-12-23
  • 2022-01-01
  • 2021-09-15
  • 2022-12-23
  • 2022-12-23
猜你喜欢
  • 2022-02-17
  • 2021-11-15
  • 2021-11-18
  • 2021-11-06
  • 2022-03-09
  • 2021-10-15
  • 2020-04-19
相关资源
相似解决方案