美文网首页深入浅出Netty源码剖析
LengthFieldBasedFrameDecoder 基于长

LengthFieldBasedFrameDecoder 基于长

作者: 想去山上定居 | 来源:发表于2017-01-03 11:23 被阅读105次

在自定义协议中,我们把每一个协议个体称为一帧数据,对不同的请求或者响应每一帧的数据长度都基本不一样,同一个请求在不同时刻发出可能获得的响应长度也是不一样的,那么我们要如何获取完整的一帧数据呢?

基于特定符号:我们可以再帧数据的末尾加上"$#$"、"\r\n\r\n" 等特定符号,当解码器读取到这些特定符号说明这一帧数据读取完毕。
基于长度字段:规定帧数据的特定字段代表帧数据的长度,解析帧数据的时候,先读取该字段的值,得知整个帧的长度,知道帧数据的长度之后再读取剩下的数据就简单多了。

LengthFieldBasedFrameDecoder 就是基于长度字段的帧解码器,理解该解码器知道两个东西就够了,长度字段在哪里?长度字段的值从哪里开始?

长度字段在哪里?

先来假设一帧数据,一开始我们是不知道这一帧数据有多长的,就像下面这样子,第一步我们就要找长度字段在哪里,说明是自定义协议,那么我们就规定前一个字节数据代表帧的长度,当然如果你喜欢你可以规定第3 个字节或者第3-4 个字段代表帧的长度。看下面的帧数据的第一个字节数据为 0x9C ,就是156,那么这156 怎么理解呢?

9C 8D 2A 88 ....

长度字段的值从哪里开始?

在自定义协议的时候一般格式为:协议头 + 消息体,不同的编码习惯可能在产生不同的封装实体,例如,1. 协议头封装为一个对象,消息体封装为一个对象;2. 还可以消息体对象包含了协议头。根据不同的封装方式就可能产生156 的开始位置不同,假设前四个字段是协议头,可以得出:

方式1:156 从第4 个字节开始算,共有156 + 4 个字节
方式2:156 从第0 个字节开始算,共有156 + 0 个字节

LengthFieldBasedFrameDecoder 的构造函数

明白了上面两个问题之后再来看这个解密器就简单多了。


public LengthFieldBasedFrameDecoder(
        ByteOrder byteOrder, 
        int maxFrameLength, 
        int lengthFieldOffset, 
        int lengthFieldLength,        
        int lengthAdjustment, 
        int initialBytesToStrip, 
        boolean failFast
) {
this.byteOrder = byteOrder;
this.maxFrameLength = maxFrameLength;
this.lengthFieldOffset = lengthFieldOffset;
this.lengthFieldLength = lengthFieldLength;
this.lengthAdjustment = lengthAdjustment;
lengthFieldEndOffset = lengthFieldOffset + lengthFieldLength;
this.initialBytesToStrip = initialBytesToStrip;
this.failFast = failFast;
}

ByteOrder 网络字节序

这个概念涉及到底层的知识,我们不关心,有一个构造方式没有该参数的,用那个就好。

maxFrameLength 最大帧长度

超过该值得帧都不解密

lengthFieldOffset 长度字段偏移量

这个是我们找长度字段的开始位置,看下面例子:

第0 个字节开始:lengthFieldOffset = 0
第1 个字节开始:lengthFieldOffset = 1
第9 个字节开始:lengthFieldOffset = 9

lengthFieldLength 长度字段的长度

第0 个字节为长度字段:lengthFieldLength = 1
第1-2 个字节为长度字段:lengthFieldLength = 2
第9-13 个字节为长度字段:lengthFieldLength = 4

可以看到通过lengthFieldOffset 和 lengthFieldLength 我们知道了长度字段在哪里了。

lengthAdjustment 字段长度的值的调整长度

lengthAdjustment = 4,lengthFieldOffset + lengthFieldLength 计算出的值为156,那么最终得到的字段长度的值为 156 + 4 = 160
lengthAdjustment = 0,lengthFieldOffset + lengthFieldLength =156,那么最终得到的字段长度的值为 156 + 0 = 156
lengthAdjustment = -4,lengthFieldOffset + lengthFieldLength =156,那么最终得到的字段长度的值为 156 - 4 = 152

到了这里我们确定长度字段的值了。

initialBytesToStrip 长度字段的值从哪里开始?

从字段的表面意思看:初始化的时候需要跳过多少个字节数,也是就是从哪里开始算的意思啦。

failFast 当帧长度超过最大帧长度的时候是否抛出异常

不抛出:不需要重连,但是发送发需要发送整帧数据,发送方当作接受方已经接受了数据。
抛出:需要重连。

一帧数据的长度

了解了构造方法之后我们来算一下一帧数据的长度

lengthValue = *(lengthFieldOffset + lengthFieldLength)

contentLength = lengthValue + lengthAdjustment

frameLength = initialBytesToStrip + contentLength(协议头 + 消息体)

相关文章

网友评论

    本文标题:LengthFieldBasedFrameDecoder 基于长

    本文链接:https://www.haomeiwen.com/subject/mqbgvttx.html