Netty中的解码器介绍


在TCP传输中,由于拆包粘包的存在,会导致半包读写的问题。
导致拆包粘包问题原因:
1.应用程序写入的字节数大于套接字缓冲区的大小
2.进行MMS(最大报文段长度)大小的TCP分段
3.以太网帧的payload大于MTU进行IP分片
以上问题可以参考文章:https://blog.csdn.net/q1007729991/article/details/69668576
和 https://blog.51cto.com/michaeljinxq/1215174

半包读写的常用解决方案如下:
1.消息定长 ,例如固定数据报文的长度为200字节,不够长度则空格补齐
2.在包尾增加回车换行符进行分割, 例如FTP协议
3.将消息分为消息头和消息体,消息头中包含消息总长度(或者消息体长度)字段,通常的设计思路是为消息头的第一个字段使用int32来表示消息的总长度

以下介绍Netty中自带解码器解决半包读写问题

LengthFieldBasedFrameDecoder解码器

这个解码器包含以下三个参数
maxFrameLength 发送的数据帧最大长度
lengthFieldOffset 长度域字段起始偏移量
lengthFieldLength 长度域字段占用长度
lengthAdjustment 读取消息题的长度调整长度
initialBytesToStrip 消息题读取的起始偏移量

场景一

消息编码后通过设置参数能够自动将消息解码
lengthFieldOffset 和 lengthFieldLength 能够确定读取到长度域字段的值,从而确定消息体body的大小,然后加上长度域字段的 4长度,就能够完整确定一条消息的长度
在这里插入图片描述

场景二

在场景一的基础上确定了整个消息的长度,设置initialBytesToStrip参数是确定读取整个消息需要丢弃的长度,这里是丢弃掉了长度域的长度,读取整个消息体的内容。
在这里插入图片描述

场景三

与上面两个场景不同的是,这里的长度域字段表示的值是整个消息的长度。所以这个时候通过lengthAdjustment 参数调整要读取的消息体的长度。以下示例中,读取到长度域的值再加上-4就是消息体的长度,就能读取到消息体。从而获得整个消息。又由于没有丢弃任何长度字节,所以获得整个消息。
在这里插入图片描述

场景四

在场景三的基础上,增加了initialBytesToStrip参数,丢弃了长度域字节,获取到消息体。
在这里插入图片描述

场景五

在场景四的基础上增加了一个请求头字段
在这里插入图片描述

场景六

在场景五的基础上调整参数,读取整条消息
在这里插入图片描述

其它场景大家可以自己去组合探索,归根结底 lengthFieldOffset参数确定长度域字段的读取起始位置,lengthFieldLength 确定读取长度域的长度,从而读取到长度值。 长度值可能是消息题的长度值,也可能是整个消息的长度值。再由长度值加上 lengthAdjustment 参数值确定要读取的消息长度。最后initialBytesToStrip 参数确定从哪个位置开始读取消息的长度。

LineBasedFrameDecoder 换行符解码器

这个解码器通过识别换行符解决拆包粘包导致的半包读问题
使用方式:

SocketChannel.pipeline().addLast(new LineBasedFrameDecoder(4096));

DelimiterBasedFrameDecoder使用自定义标识符解码器

这个解码器通过使用用户自定义的标识符解决半包读问题
使用方式:

//使用 $ 作为标识符
ByteBuf byteBuf = Unpooled.copiedBuffer("$".getBytes());
SocketChannel.pipeline().addLast(new DelimiterBasedFrameDecoder(4096,byteBuf))

FixedLengthFrameDecoder固定长度解码器

每次读取固定长度的自己解决半包读问题

SocketChannel.pipeline().addLast(new FixedLengthFrameDecoder(100));
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值