1.ChannelPipeline

ChannelPipeline是ChannelHandler的容器,负责ChannelHandler的管理和事件拦截与调度
image.png
1.底层的SocketChannel read()方法读取ByteBuf,触发ChannelRead事件,由IO线程NioEventLoop调用ChannelPipeline的fireChannelRead(Object msg)方法,将消息(ByteBuf)传输到ChannelPipeline中
2.消息依次被HeadHandler,等一系列ChannelHandler拦截和处理,在这个过程中,任何ChannelHandler都可以中断当前的流程,结束消息的传递
3.调用ChannelHandlerContext的write方法发送消息,消息从TailHandler开始,途径一系列ChannelHandler,最终添加到消息缓冲区中等待刷新和发送,在此过程中也可以中断消息的传递,例如编码失败
image.png
image.png
image.png
image.png


2.ChannelHandler

image.png


ChannelHandlerAdapter

image.png


ByteToMessageDecoder

image.pngimage.png


MessageToMessageDecoder

image.png


LengthFieldBasedFrameDecoder(半包解码器)

image.png

公式: 发送数据包长度 = 长度域的值 + lengthFieldOffset + lengthFieldLength + lengthAdjustment

LengthFieldBasedFrameDecoder - 6个参数解释

LengthFieldBasedFrameDecoder是自定义长度解码器,所以构造函数中6个参数,基本都围绕那个定义长度域,进行的描述。

  1. maxFrameLength - 是指最大包长度,如果Netty最终生成的数据包超过这个长度,Netty就会报错。
  2. lengthFieldOffset - 定义长度域位于发送的字节数组中的下标。换句话说:发送的字节数组中下标为${lengthFieldOffset}的地方是长度域的开始地方
  3. lengthFieldLength - 用于描述定义的长度域的长度。换句话说:发送字节数组bytes时, 字节数组bytes[lengthFieldOffset, lengthFieldOffset+lengthFieldLength]域对应于的定义长度域部分
  4. 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!!!

  5. initialBytesToStrip - 接收到的发送数据包,去除前initialBytesToStrip位

    initialBytesToStrip之前的几个参数,已经足够netty识别出整个数据包了,但是很多时候,调用者只关心包的内容,包的头部完全可以丢弃掉,initialBytesToStrip就是用来告诉Netty,识别出整个数据包之后,我只要从initialBytesToStrip起的数据

  6. failFast - true: 读取到长度域超过maxFrameLength,就抛出一个 TooLongFrameException。false: 只有真正读取完长度域的值表示的字节之后,才会抛出 TooLongFrameException,默认情况下设置为true,建议不要修改,否则可能会造成内存溢出

  7. ByteOrder - 数据存储采用大端模式或小端模式 ,因为Netty要读取Length字段的值,所以大端小端要设置好,默认Netty是大端序ByteOrder.BIG_ENDIAN。
    1. public LengthFieldBasedFrameDecoder(
    2. ByteOrder byteOrder, int maxFrameLength, int lengthFieldOffset,
    3. int lengthFieldLength,int lengthAdjustment, int initialBytesToStrip,
    4. boolean failFast) {
    5. //...
    6. }

MessageToByteEncoder

image.png


MessageToMessageEncoder

image.png


LengthFieldPrepender

image.png
image.png


ChannelHandler源码分析

image.png
image.png


ByteTomessageDecoder

image.png
1.首先判断msg对象是否为ByteBuf
image.png
image.png
image.png


MessageToMessageDecoder

MessageToMessageDecoder负责将一个POJO对象解码成为另一个POJO对象
image.png
image.png

image.png


LengthFieldBasedFrameDecoder

image.png
image.png
image.png
image.png
image.png
image.pngimage.png
image.png

image.png
image.png