1.ChannelPipeline
ChannelPipeline是ChannelHandler的容器,负责ChannelHandler的管理和事件拦截与调度
1.底层的SocketChannel read()方法读取ByteBuf,触发ChannelRead事件,由IO线程NioEventLoop调用ChannelPipeline的fireChannelRead(Object msg)方法,将消息(ByteBuf)传输到ChannelPipeline中
2.消息依次被HeadHandler,等一系列ChannelHandler拦截和处理,在这个过程中,任何ChannelHandler都可以中断当前的流程,结束消息的传递
3.调用ChannelHandlerContext的write方法发送消息,消息从TailHandler开始,途径一系列ChannelHandler,最终添加到消息缓冲区中等待刷新和发送,在此过程中也可以中断消息的传递,例如编码失败
2.ChannelHandler
ChannelHandlerAdapter
ByteToMessageDecoder
MessageToMessageDecoder
LengthFieldBasedFrameDecoder(半包解码器)
公式: 发送数据包长度 = 长度域的值 + lengthFieldOffset + lengthFieldLength + lengthAdjustment
LengthFieldBasedFrameDecoder - 6个参数解释
LengthFieldBasedFrameDecoder是自定义长度解码器,所以构造函数中6个参数,基本都围绕那个定义长度域,进行的描述。
- maxFrameLength - 是指最大包长度,如果Netty最终生成的数据包超过这个长度,Netty就会报错。
- lengthFieldOffset - 定义长度域位于发送的字节数组中的下标。换句话说:发送的字节数组中下标为${lengthFieldOffset}的地方是长度域的开始地方
- lengthFieldLength - 用于描述定义的长度域的长度。换句话说:发送字节数组bytes时, 字节数组bytes[lengthFieldOffset, lengthFieldOffset+lengthFieldLength]域对应于的定义长度域部分
lengthAdjustment - 满足公式: 发送的字节数组bytes.length - lengthFieldLength = bytes[lengthFieldOffset, lengthFieldOffset+lengthFieldLength] + lengthFieldOffset + lengthAdjustment
当Netty利用lengthFieldOffset(偏移位)和lengthFieldLength(Length字段长度)成功读出Length字段的值后,Netty认为这个值是指从Length字段之后,到包结束一共还有多少字节,如果这个值是13,那么Netty就会再等待13个Byte的数据到达后,拼接成一个完整的包。但是更多时候,Length字段的长度,是指整个包的长度,如果是这种情况,当Netty读出Length字段的时候,它已经读取了包的4个Byte的数据,所以,后续未到达的数据只有9个Byte,即13 - 4 = 9,这个时候,就要用lengthAdjustment来告诉Netty,后续的数据并没有13个Byte,要减掉4个Byte,所以lengthAdjustment要设为 -4!!!
initialBytesToStrip - 接收到的发送数据包,去除前initialBytesToStrip位
initialBytesToStrip之前的几个参数,已经足够netty识别出整个数据包了,但是很多时候,调用者只关心包的内容,包的头部完全可以丢弃掉,initialBytesToStrip就是用来告诉Netty,识别出整个数据包之后,我只要从initialBytesToStrip起的数据
failFast - true: 读取到长度域超过maxFrameLength,就抛出一个 TooLongFrameException。false: 只有真正读取完长度域的值表示的字节之后,才会抛出 TooLongFrameException,默认情况下设置为true,建议不要修改,否则可能会造成内存溢出
- ByteOrder - 数据存储采用大端模式或小端模式 ,因为Netty要读取Length字段的值,所以大端小端要设置好,默认Netty是大端序ByteOrder.BIG_ENDIAN。
public LengthFieldBasedFrameDecoder(
ByteOrder byteOrder, int maxFrameLength, int lengthFieldOffset,
int lengthFieldLength,int lengthAdjustment, int initialBytesToStrip,
boolean failFast) {
//...
}
MessageToByteEncoder
MessageToMessageEncoder
LengthFieldPrepender
ChannelHandler源码分析
ByteTomessageDecoder
1.首先判断msg对象是否为ByteBuf
MessageToMessageDecoder
MessageToMessageDecoder负责将一个POJO对象解码成为另一个POJO对象