Netty常用招式——ChannelHandler与编解码(二)

简介: Netty常用招式——ChannelHandler与编解码(二)

3.Netty有哪些开箱即用的解码器


作为一个优秀的网络编程框架,Netty除了支持扩展自定义编解码器外,还提供了非常丰富的开箱即用的编解码器。尤其是针对我们上文1.2节中提过的三种解决「粘包/拆包问题」的方式,都有开箱即用的实现。


3.1固定长度解码器FixedLengthFrameDecoder


这个解码器上文已经提到过,对应1.2节中的「固定长度解码」,这里再稍微展开一下。

113.png


通过构造函数配置固定长度 frameLength,然后在decode时,按照frameLength 进行解码。


  • 当读取到长度大小为 frameLength 的消息,那么解码器认为已经获取到了一个完整的消息。
  • 当消息长度小于 frameLength,FixedLengthFrameDecoder 解码器会一直等后续数据包的到达,直至获得完整的消息。


3.2特殊分隔符解码DelimiterBasedFrameDecoder


这个解码器对应1.2节中的「特殊分隔符解码」,也是一个继承自ByteToMessageDecoder的解码器。


这个解码器会使用 1个 或 多个 符号delimiter 对传入的消息(ByteBuf)进行解码。


我们看一下构造器,了解一下几个重要参数。

114.png


  • maxFranmeLength


maxFranmeLength 是待处理消息的最大长度限制。如果超过 maxFranmeLength 还没有检测到指定分隔符,将会抛出 TooLongFrameException。


  • stripDelimiter


stripDelimiter是一个boolean类型, 用于判断解码后得到的消息是否移除分隔符。如果 stripDelimiter=false,那么解码后的消息内容就会保留分隔符信息。


  • failFast


failFast是一个boolean类型。如果为true,那么消息在超出 maxFranmeLength 后,会立即抛出 TooLongFrameException。如果为false,那么会等到解码出一个完整的消息后才会抛出TooLongFrameException。


  • delimiters


delimiters 的类型是 ByteBuf 数组,可以在构造器中同时传入多个分隔符,但是在解析时,最终会选择长度最短的分隔符进行消息拆分。

例如收到的数据为:


ABCD\nEFG\r\n


如果指定的分隔符为 \n 和 \r\n,那么会解码出两个消息。


ABCD   EFG


如果指定的特定分隔符只有 \r\n,那么只会解码出一个消息:


ABCD\nEFG


3.3长度域解码器LengthFieIdBasedFrameDecoder


这个解码器是生产实践中运用比较广泛的一种(比如RocketMQ),相对复杂,但是特别灵活,基本能覆盖各种基于长度进行拆包的方案,比如1.2节中提到的「消息长度+内容」的方案。


使用这个解码器的时候,重点需要了解4个参数,掌握了参数的设置,就能快速实现不同的基于长度的拆包解码方案。


参数名

类型

含义

lengthFieldOffset

int

长度字段的偏移量。表示「长度域」的起始位置

lengthFieldLength

int

长度字段所占用的字节数

lengthAdjustment

int

消息长度的修正值。表示一些复杂协议中,会在「长度域」添加一些其他内容,如版本号、消息类型等,这就需要修正值进行修正处理

initialBytesToStrip

int

解码后需要跳过的初始字节数。表示消息内容数据的起始位置


1)解码方案一:基于消息长度 + 消息内容,解码结果不截断消息头


报文只包含消息长度 Length 和消息内容 Content 字段,其中 Length 为 16 进制表示,共占用 2 字节,Length 的值 0x000C 代表 Content 占用 12 字节。


参数名

取值 

lengthFieldOffset

0

lengthFieldLength

2

lengthAdjustment

0

initialBytesToStrip

0(表示解码结果不截断消息头)


解码示例:

115.png


2)解码方案二:基于消息长度 + 消息内容,解码结果截断


与方案一不同之处在于,解码结果会截断消息头(跳过2字节)


参数名

取值 

lengthFieldOffset

0

lengthFieldLength

2

lengthAdjustment

0

initialBytesToStrip

2(表示跳过 Length 字段的字节长度,解码后 只包含 消息内容)


解码示例:

116.png



3)解码方案三:基于消息头 + 消息长度 + 消息内容


消息起始位置添加特殊消息头,消息长度 Length字段 后移。


参数名

取值 

lengthFieldOffset

2

lengthFieldLength

3

lengthAdjustment

0

initialBytesToStrip

0(表示解码结果不截断消息头)


解码示例:


117.png


4)解码方案四:基于消息长度 + 消息头 + 消息内容


消息起始位置为消息长度 Length字段,后面并不直接添加 消息内容,而是先添加 消息头header,再添加 消息内容。


参数名

取值 

lengthFieldOffset

0

lengthFieldLength

3

lengthAdjustment

2 (Header1的长度)

initialBytesToStrip

0(表示解码结果不截断消息头)


解码示例:

118.png


由于 Length 后面不是马上添加content,所以需要加上 lengthAdjustment(2 字节)才能得到 Header + Content 的内容(14 字节)。


4.小结


来简单回顾下吧。


本文主要介绍了ChannelHandler的一种典型应用场景——编解码器。


编解码器核心关注点在于「粘包/拆包」的处理,我们介绍了「粘包/拆包」产生的原因以及常用解决方案。然后说明了如何使用Netty框架实现自定义编解码器。


最后,介绍了Netty中非常好用的几个开箱即用的编解码器。


参考书目:


《Netty 实战》

《Netty4核心原理》




目录
相关文章
|
2月前
|
网络协议 Java 容器
《跟闪电侠学Netty》阅读笔记 - ChannelHandler 生命周期
《跟闪电侠学Netty》阅读笔记 - ChannelHandler 生命周期
51 0
《跟闪电侠学Netty》阅读笔记 - ChannelHandler 生命周期
|
2月前
|
编解码 开发者
Netty Review - 深入理解Netty: ChannelHandler的生命周期与事件处理机制
Netty Review - 深入理解Netty: ChannelHandler的生命周期与事件处理机制
74 0
|
2月前
|
编解码
Netty Review - 优化Netty通信:如何应对粘包和拆包挑战_自定义长度分包编解码码器
Netty Review - 优化Netty通信:如何应对粘包和拆包挑战_自定义长度分包编解码码器
56 0
|
2月前
|
编解码 JSON 网络协议
Netty使用篇:Http协议编解码
Netty使用篇:Http协议编解码
|
9月前
|
存储 前端开发 Java
Netty 爱好者必看!一文详解 ChannelHandler 家族,助你快速掌握 Netty 开发技巧!
Netty 爱好者必看!一文详解 ChannelHandler 家族,助你快速掌握 Netty 开发技巧!
199 0
|
12月前
|
移动开发 安全 前端开发
Netty实战(十二)预置的ChannelHandler和编解码器(二)
HTTPS、WebSocket的添加使用和大型数据写入以及几种常见的序列化)
66 0
|
12月前
|
安全 Java 关系型数据库
Netty实战(十一)预置的ChannelHandler和编解码器(一)
作为一个通讯框架,通讯数据的安全性也是不可或缺的一部分。一般常见的像TLS/SSL这样的安全协议我们都应该熟悉。 我们在访问安全网站时都遇到过这些协议,但是它们也可用于其他不是基于HTTP的应用程序,如安全SMTP(SMTPS)邮件服务器甚至是关系型数据库系统。
114 0
|
XML 存储 编解码
如何修正Netty编解码的缺陷
如何修正Netty编解码的缺陷
107 0
如何修正Netty编解码的缺陷
|
存储 缓存 NoSQL
跟着源码学IM(十一):一套基于Netty的分布式高可用IM详细设计与实现(有源码)
本文将要分享的是如何从零实现一套基于Netty框架的分布式高可用IM系统,它将支持长连接网关管理、单聊、群聊、聊天记录查询、离线消息存储、消息推送、心跳、分布式唯一ID、红包、消息同步等功能,并且还支持集群部署。
13294 1
|
16天前
|
机器学习/深度学习 缓存 算法
netty源码解解析(4.0)-25 ByteBuf内存池:PoolArena-PoolChunk
netty源码解解析(4.0)-25 ByteBuf内存池:PoolArena-PoolChunk