我之前学习Netty的课程时出现了LengthFieldBasedFrameDecoder解码器,当时我只想了解学习这门技术,所以很多技术点我都没有深入研究,现在工作有这方面的需要了,我需要开始深入研究一下。
LengthFieldBasedFrameDecoder解码器主要用于自定义协议,通常协议的格式为:
header | length | body
构造函数
其构造函数如下:
|
|
参数含义分别如下:
-
maxFrameLength:最大帧长度。也就是可以接收的数据的最大长度。如果超过,此次数据会被丢弃
-
lengthFieldOffset:长度域偏移。就是说数据开始的几个字节可能不是表示数据长度,需要后移几个字节才是长度域
-
lengthFieldLength:长度域字节数。用几个字节来表示数据长度
-
lengthAdjustment:数据长度修正。因为长度域指定的长度可以是header + body的整个长度,也可以只是body的长度。如果表示header + body的整个长度,那么我们需要修正数据长度
-
initialBytesToStrip:跳过的字节数。如果你需要接收header+body的所有数据,此值就是0,如果你只想接收body数据,那么需要跳过header所占用的字节数。
原课程中的应用
如下代码为我对该类的应用
|
|
我的代码源于之前学习的课程,我的方案中我使用了一个叫做魔数的东西,如果用户传递的消息的魔数和我定义的不符合,则我会关闭消息通道。
在我的应用中,我的消息的长度可以是任意的,长度从第7个字节开始,长度本身占用四个字节。至于lengthAdjustment,由于我的length记录的就是我body的长度,所以我传递为零;因为我需要接受所有的数据,所以,initialBytesToStrip同样为零。
如果不使用该解码器该如何实现
我会在read中,判断当前可读的字节数是否大于4 + 4
,如果大于,则我会先读取7个字节作为魔数,然后再读4个字节作为长度。
在实现的过程中,我可能会将对消息的解码放在同一个解码器中实现,所以我下一步可能会持续判断可读字节数是否为消息中定义的长度,如果是,则读取该长度的字节数,转码为package对象,然然后从package对象中获得字节码数据,转成对应的消息。在该实现过程中,我进行调用了package对象进行了两次转换。
如果需要进行优化,我会选择将package对象给刨除掉,我直接在,我的消息格式大概如下:
魔数 | 协议编号 | 消息体长度 | 消息内容
(实际上协议编号和消息体长度的先后顺序没有任何影响,所以没有必要纠结其前后)
我暂时不打算考虑协议版本号、编解码算法等问题,我直接默认用protobuf。