Netty(三) TCP粘包问题和解码器

TCP粘包和半包问题

我们已知TCP全双工的流传输协议,且TCP会将数据写入内核的缓冲区中,再由应用程序读取出数据。在异步传输的场景下,应用程序无法保证读取出的数据是期望的数据内容。

比如我们想要的数据是ABC123,那么应用程序从缓冲区读取出可能是ABC12 ,这时3还没被写入缓冲区;也可能是23ABC123,这是上次23没有被读取走,跟下一条数据一起被读取出来;

当应用程序读取的数据多于正常数据,23ABC123,这就是粘包;
当应用程序读取的数据少于正常数据,ABC12,这就是半包;

粘包和半包都会导致数据格式错误,导致应用程序出错!

解决思路

  1. 约定消息定长,应用程序按照固定长度,去缓冲区读取
  2. 消息结束符号:包括最常用的字符串结束符\n 和其他自定义符号,适用于字符串文本传输;
  3. 自定义消息头部和尾部:通过消息头和消息尾标记一条消息的开始和结束,并在消息头中定义消息体的长度

Netty定长解码器 FixedLengthFrameDecoder

根据类名,翻译过来就能知道这是一个基于固定长度的解码器,什么意思呢?就是在初始化这个解码器时,指定一个 int 类型的数值:frameLength,后面在解码时,每当读到 frameLength 长度的字节时,就解码出一个数据对象。例如:当发送方发送了四次数据,分别是 A、BC、DEFG、HI,一共 9 个字节,如果我们指定解码器的固定长度 frameLength = 3,那么就表示每 3 个字节解一次码,那么解码出来的结果结果就是:ABC、DEF、GHI。

// 入参 maxLength:最大长度
FixedLengthFrameDecoder decoder = new FixedLengthFrameDecoder (1024) ;

Netty换行符解码器 LineBaseFrameDecoder

回车换行解码器,如果消息是以字符串文本形式且以回车换行符(\r\n 或者 \n)作为消息结束的标识,则可以使用该解码器进行解码;

原理:

  1. 依次遍历ByteBuf中的可读字节,判断是否有 \r\n ,如果则有标记为结束位置,从可读起始索引位到标记结束位为一行数据;
  2. 支持配置单行长度,若读取至最大长度仍未发现换行符,则抛出异常,并丢弃ByteBuf的数据,防止积压导致内存溢出
// 入参 maxLength 最大长度
LineBasedFrameDecoder  decoder = new LineBasedFrameDecoder( 100 ) ;

Netty分隔符解码器

按照特定分割符进行解码的解码器,回车换行符解码器实际就是一种特殊的分隔符解码器;
分隔符Delimiter是以ByteBuf作为入参

// ByteBuf 分隔符
ByteBuf delimiter = UnPooled.copiedBuffer( "XXXX".getBytes() );
/ **
*  maxLength : 最大长度
*  delimiter :分隔符
*/
DelimiterBasedFrameDecoder decoder = new DelimiterBaseFrameDecoder(1000 , delimiter);

Netty通用字节流消息头解码器

按照私有协议中的消息头作分割,并取消息头中的消息体长度字段,分割出消息体的解码器,是灵活度最高的解码器;

它有4个,重要参数:

  • lengthFieldOffset: 长度属性之前的偏移量
  • lengthFieldLength:长度属性自身的长度
  • lengthAdjustment: 从长度属性到消息体之间的偏移量
  • initialBytesToStrip: 分割出消息体之前需要忽略的字节数量
// 1024是最大长度 maxLength
LengthFieldBasedFrameDecoder decoder = new LengthFieldBasedFrameDecoder (1024,2,4,4,6);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值