• LengthFieldBasedFrameDecoder解析


    解码器LengthFieldBasedFrameDecoder, 从名字上可以猜测出来, 它是基于长度的解码器.

    Netty从TCP缓冲区中读取字节, 把这些字节交给LengthFieldBasedFrameDecoder进行解码, 解码的操作是根据设定的规则, 根据规则, 从字节中解码出来有意义的数据, 然后把数据再交给后续的Handler处理.

    接下来看下, 它是如何根据规则解码的.

    在这里插入图片描述如上图, 从网络中读取到的数据是基于流的, 而且是有方向的. 然而数据是没有边界的, 不知道从哪儿到哪儿是一个完整的数据, 下一个数据又是从哪个到哪个. 因此应用层需要设定规则, 根据规则就可以知道数据的边界在哪儿.


    在这里插入图片描述
    如上图, 便是根据设定的规则, 就可以’筛选’出来真正有意义的数据(data)在哪个. 而且允许每个data的长度是不一样大小.

    那么就要说下这个规则是什么了. 规则是由4个主要的属性构成, lengthFieldOffset, lengthFieldLength, lengthAdjustment, initialBytesToStrip. 通过一个数据块为例介绍这4个属性.


    在这里插入图片描述如上图, 从红色箭头指向的位置开始读取数据.lengthFieldOffset表示长度字段的偏移量, 经过lengthFieldOffset之后, 箭头指向了下一个位置. 如果lengthFieldOffset=3, 那么箭头需要向右边走3个字节.


    在这里插入图片描述接下来, lengthFieldLength表示长度字段的长度(好绕口). 如果lengthFieldLength=4, 那么就会从上图红色位置向后读取4个字节, 把4个字节里面的内容作为真正data的长度. 而且lengthFieldLength的取值不是任意的, 它只能取值1,2,3,4,8. 具体原因后面的源码会说明.


    在这里插入图片描述如上图, 假如lengthFieldLength=4, 读取4个字节的内容是0x00000010(十六进制表示), 十进制就是16, 也就是说, 数据data的长度是16个字节. 但是这里稍等下, 需要介绍下一个关键属性.

    lengthAdjustment表示长度调整. 调整什么呢? 还是要说下lengthFieldLength. lengthFieldLength里面的内容是16, 虽然这个16表示长度, 但是它是表示真正数据data的长度,还是表示整个的长度呢, 或者其他呢. 因此要想真正表示真正数据data的长度, 必须用lengthFieldLength的内容值+lengthAdjustment的值. 如果lengthAdjustment=-5, 也就是用16+(-5)=11, 即从上图红色位置继续向后读取11个字节才能真正的把数据读取完整, 读取少了或多了都不行.

    到这里, 已经把一个完整的数据块读取完成了. 但是呢, 真正表示业务数据的内容是data部分.我们不想要前面的lengthFieldOffset和lengthFieldLength部分,这里就需要使用initialBytesToStrip. 它表示跳过多少字节. 如果initialBytesToStrip=7, 那么就是说要跳过7个字节, 把剩余部分传给下游的Handler继续处理.


    在这里插入图片描述以上就是4个主要属性的解释, 从源码中拿一个具体的’案例’再温习下.


    在这里插入图片描述
    从最左边开始读取数据, lengthFieldOffset=1, 那么向后读取1个字节, lengthFieldLength=2, 向后读取2个字节, 读取到的内容是0x0010(十六进制), 十进制就是16, 由于lengthAdjustment=-3, 因此16+(-3)=13, 于是继续向后读取13个字节. 就会把0xFE和"HELLO, WORLD"这13个字节读取到. 到目前为止, 读取到的内容是0xCA0010FE和"HELLO, WORLD"共16个字节. 又initialBytesToStrip=3, 因此从16个字节的开头跳过3个字节, 跳过了0xCA0010这3个字节, 最后剩下0xFE和"HELLO, WORLD"传给了下游的Handler.

  • 相关阅读:
    eclipse 粘贴字符串自动添加转义符
    原创 导出微信收藏到电脑
    解决 eclipse中properties文件编码问题
    jetty 内嵌服务
    解决log4j:WARN No appenders could be found for logger
    解决JettyMavenPlugin: Failed to load class "org.slf4j.impl.StaticLoggerBinder"
    读取properties文件方式
    解决ssh远程登陆linux显示-bash-4.1$
    解决weblogic.net.http.SOAPHttpsURLConnection incompatible with javax.net.ssl.HttpsURLConnection
    解决java.io.IOException: HTTPS hostname wrong: should be
  • 原文地址:https://www.cnblogs.com/huifeidezhuzai/p/16277046.html
Copyright © 2020-2023  润新知