Netty之基于长度域的动态解码

本文深入解析Netty的LengthFieldBasedFrameDecoder,用于动态解码基于长度域的消息。通过实例分析参数含义,揭示解码过程,包括丢弃模式的处理,帮助理解如何处理动态长度的数据包。
摘要由CSDN通过智能技术生成

前言

这篇文章算是上篇文章 Netty解码器源码分析 的扩展篇 ,这里单独开一篇讲解这个特殊的解码器LengthFieldBasedFrameDecoder。

首先,它有什么用呢?有什么应用场景吗?这边我举一个例子,dubbo底层使用了Netty做了服务间通信来完成远程调用,其中应用层协议使用了自定义dubbo协议
在这里插入图片描述

偏移量(Bit) 字段 取值
0 ~ 7 魔数高位 0xda00
8 ~ 15 魔数低位 0xbb
16 数据包类型 0 - Response, 1 - Request
17 调用方式 仅在第16位被设为1的情况下有效,0 - 单向调用,1 - 双向调用
18 事件标识 0 - 当前数据包是请求或响应包,1 - 当前数据包是心跳包
19 ~ 23 序列化器编号 2 - Hessian2Serialization 3 - JavaSerialization 4 - CompactedJavaSerialization 6 - FastJsonSerialization 7 - NativeJavaSerialization 8 - KryoSerialization 9 - FstSerialization
24 ~ 31 状态 20 - OK 30 - CLIENT_TIMEOUT 31 - SERVER_TIMEOUT 40 - BAD_REQUEST 50 - BAD_RESPONSE …
32 ~ 95 请求编号 共8字节,运行时生成
96 ~ 127 消息体长度 运行时计算

图片、表格信息均摘自dubbo官方文档

以上表格代表整个消息头,也就是说,整个消息头的偏移量是固定的,例如96~127的偏移量的这个位置就是代表着消息体的长度,而不固定的是消息体,dubbo协议中消息体代表dubbo远程调用的一些信息例如接口版本、被调用的方法名、方法参数等等,这些信息是不一定的,这部分长度需要运行时才能计算出来,并且放入消息头中。那么,在解码的时候,我们就可以先接收固定长度(偏移量127bit长度)的消息头,将消息中固定偏移量(96~127)的内容先取出来,就可以知道接下来需要再接收多少长度的消息体,这样就算一个完整的数据包了。以上流程即可解码一个动态长度的数据包。

那么接下来就开始介绍,基于长度域的动态解码器。

基于长度域的动态解码器

使用介绍

在开始源码分析之前,这里先介绍一下怎么使用。如果有下载Netty源码,就可以看到LengthFieldBasedFrameDecoder中的类头有一大串注释,这串注释其实就很好的介绍了这个类的使用。那么就以这个类头来分析这个类能做什么。

先介绍一下四个参数分别什么意思,可以大致先了解一下,往下看你就更能理解这些参数了

  1. 需要拿到的动态长度信息的起始点(偏移量),dubbo协议中即为96
  2. 长度信息的长度,dubbo协议中即为32
  3. 长度修正量
  4. 需要剥离的长度
  • lengthFieldOffset :0
  • lengthFieldLength :2
  • lengthAdjustment :0
  • initialBytesToStrip :0
* BEFORE DECODE (14 bytes)         AFTER DECODE (14 bytes)
* +--------+----------------+      +--------+----------------+
* | Length | Actual Content |----->| Length | Actual Content |
* | 0x000C | "HELLO, WORLD" |      | 0x000C | "HELLO, WORLD" |
* +--------+----------------+      +--------+----------------+

首先,从0开始,长度为2,"HELLO, WORLD"字符串为12字节,也就是说前面Length占2字节,解码器截取前两字节,16进制0x000C = 12,加上lengthAdjustment,最终表示数据长度有12字节,剥离长度为0,则最终为14字节的完整数据。

  • lengthFieldOffset :0
  • lengthFieldLength :2
  • lengthAdjustment :0
  • initialBytesToStrip :2
* BEFORE DECODE (14 bytes)         AFTER DECODE (12 bytes)
* +--------+----------------+      +----------------+
* | Length | Actual Content |----->| Actual Content |
* | 0x000C | "HELLO, WORLD" |      | "HELLO, WORLD" |
* +--------+----------------+      +----------------+

这里和上面不同的就是,剥离长度为2,则剥离前两字节的内容,很简单,Length字段被剥离了,剩下12字节的数据包。

  • lengthFieldOffset :0
  • lengthFieldLength :2
  • lengthAdjustment :-2
  • initialBytesToStrip :0
* BEFORE DECODE (14 bytes)         AFTER DECODE (14 bytes)
* +--------+----------------+      +--------+----------------+
* | Length | Actual Content |----->| Length | Actual Content |
* | 0x000E | "HELLO, WORLD" |      | 0x000E | "HELLO, WORLD" |
* +--------+----------------+      +--------+----------------+

这里和第一个例子不同的就是修正量为-2,Length字段不再是12,而是14,也就是说计算长度的方法变了,拿到Length字段的值14之后,还需要加上修正量-2,结果还是为12字节的数据。

  • lengthFieldOffset :2
  • lengthFieldLength :3
  • lengthAdjustment :0
  • initialBytesToStrip :0
* BEFORE DECODE (17 bytes)                      AFTER DECODE (17 bytes)
* +----------+----------+----------------+      +----------+----------+----------------+
* | Header 1 |  Length  | Actual Content |----->| Header 1 |  Length  | Actual Content |
* |  0xCAFE  | 0x00000C | "HELLO, WORLD" |      |  0xCAFE  | 0x00000C | "HELLO, WORLD" |
* +----------+----------+----------------+      +----------+----------+----------------+

这里修改了偏移量的位置和Length长度的字节数,很好理解。

  • lengthFieldOffset :1
  • lengthFieldLength :2
  • lengthAdjustment :1
  • initialBytesToStrip :3
 * BEFORE DECODE (16 bytes)                       AFTER DECODE (13 bytes)
 * +------+--------+------+----------------+      +------+----------------+
 * | HDR1 | Length | HDR2 | Actual Co
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值