Netty 源码分析 08 编码Codec 01
4. Cumulator
Cumulator ,是 ByteToMessageDecoder 的内部接口。中文翻译为“累加器”,用于将读取到的数据进行累加到一起,然后再尝试解码,从而实现拆包。
也是因为 Cumulator 的累加,所以能将不完整的包累加到一起,从而完整。当然,累加的过程,没准又进入了一个不完整的包。所以,这是一个不断累加,不断解码拆包的过程。
- 对于
Cumulator#cumulate(ByteBufAllocator alloc, ByteBuf cumulation, ByteBuf in)
方法,将原有cumulation
累加上新的in
,返回“新”的 ByteBuf 对象。 - 如果
in
过大,超过cumulation
的空间上限,使用alloc
进行扩容后再累加。
4.1 MERGE_CUMULATOR
MERGE_CUMULATOR
思路是,不断使用老的 ByteBuf 累积。如果空间不够,扩容出新的 ByteBuf ,再继续进行累积。
4.2 COMPOSITE_CUMULATOR
COMPOSITE_CUMULATOR
思路是,使用 CompositeByteBuf ,组合新输入的 ByteBuf 对象,从而避免内存拷贝。
默认情况下,ByteToMessageDecoder 使用 MERGE_CUMULATOR
作为累加器。
5. ByteToMessageDecoder
io.netty.handler.codec.ByteToMessageDecoder
,继承 ChannelInboundHandlerAdapter 类,抽象基类,负责将 Byte 解码成 Message
5.2 channelRead
#channelRead(ChannelHandlerContext ctx, Object msg)
方法,读取到新的数据,进行解码
5.3 callDecode
#callDecode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out)
方法,执行解码。而解码的结果,会添加到 out
数组中
5.3.1 decodeRemovalReentryProtection
#decodeRemovalReentryProtection(ChannelHandlerContext ctx, ByteBuf in, List<Object> out)
方法,执行解码。如果 Handler 准备移除,在解码完成后,进行移除
5.4 channelReadComplete
#channelReadComplete(ChannelHandlerContext ctx)
方法
5.5 channelInactive
#channelInactive(ChannelHandlerContext ctx)
方法,通道处于未**( Inactive ),解码完剩余的消息,并释放相关资源
调用 #channelInputClosed(ChannelHandlerContext ctx, boolean callChannelInactive)
方法,执行 Channel 读取关闭的逻辑
5.6 userEventTriggered
#userEventTriggered(ChannelHandlerContext ctx, Object evt)
方法,处理 ChannelInputShutdownEvent 事件,即 Channel 关闭读取
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Codec 之 ByteToMessageDecoder(二)FrameDecoder
1. 概述
在 《精尽 Netty 源码解析 —— Codec 之 ByteToMessageDecoder(一)》 中,我们看到 ByteToMessageDecoder 有四个 FrameDecoder 实现类:
- ① FixedLengthFrameDecoder ,基于固定长度消息进行粘包拆包处理的。
- ② LengthFieldBasedFrameDecoder ,基于消息头指定消息长度进行粘包拆包处理的。
- ③ LineBasedFrameDecoder ,基于换行来进行消息粘包拆包处理的。
- ④ DelimiterBasedFrameDecoder ,基于指定消息边界方式进行粘包拆包处理的。
3. LineBasedFrameDecoder
io.netty.handler.codec.LineBasedFrameDecoder
,继承 ByteToMessageDecoder 抽象类,基于换行来进行消息粘包拆包处理的。
它会处理 "\n"
和 "\r\n"
两种换行符。
3.3 findEndOfLine
#findEndOfLine(final ByteBuf buffer)
方法,获得换行符的位置。代码如下
4. LengthFieldBasedFrameDecoder
io.netty.handler.codec.LengthFieldBasedFrameDecoder
,继承 ByteToMessageDecoder 抽象类,基于消息头指定消息长度进行粘包拆包处理的。
5. DelimiterBasedFrameDecoder
io.netty.handler.codec.DelimiterBasedFrameDecoder
,继承 ByteToMessageDecoder 抽象类,基于指定消息边界方式进行粘包拆包处理的。