Netty通信中的粘包半包问题(六)

这篇具有很好参考价值的文章主要介绍了Netty通信中的粘包半包问题(六)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1.前言

对Netty中的粘包半包问题还不了解的童鞋,可以看看之前的
Netty通信中的粘包半包问题(一到五)系列,以免产生不适如果你对Netty中的粘包半包问题已经熟悉了,可以直接阅读本文,
本文主要介绍了消息头+消息体去解决粘包半包问题。

2.LengthFieldBasedFrameDecoder

LengthFieldBasedFrameDecoder是Netty提供给我们一种消息头+消息体的一种解决思路,这种方式使用起来比较复杂,因为该类有几个核心参数需要进行设置,否则将会影响数据报文的正常读取.

  • maxFrameLength:表示的是包的最大长度
  • lengthFieldOffset:指的是长度域的偏移量,表示跳过指定个数字节之后的才是长度域
  • lengthFieldLength:记录该帧数据长度的字段,也就是长度域本身的长度
  • lengthAdjustment:长度的一个修正值,可正可负,Netty在读取到数据包的长度值N后,认为接下来的N个字节都是需要
  • initialBytesToStrip:从数据帧中跳过的字节数,表示得到一个完整的数据包之后,扔掉这个数据包中多少字节数,才是后续业务实际需要的业务数据
  • failFast:如果为true,则表示读取到长度域,它的值超过maxFrameLength,就跑出一个TooLongFrameException,如果为false只有当真正读取完长度域的值表示的字节之后,才会抛出TooLongFrameException,默认情况下为true,一般不要修改,否则可能造成内存溢出

接下来我们将通过几个例子来讲解这些参数的使用,在分析这些例子之前,建议先把上面的参数解释复制下来,用两个窗口来分析

3.示例一

Netty通信中的粘包半包问题(六),Netty,java,服务器
数据包大小:14B = 长度域为2B + “HELLO, WORLD”(单词HELLO + 一个逗号 + 一个空格 + 一个单词WORLD)
长度域的值为12B(0x000C),希望解码后保持一样,参数设置应为如下:

  • lengthFieldOffset = 0,因为在当前的例子中,长度域前面没有任何其他数据,所以这里不需要设置长度域的偏移量
  • lengthFieldLength = 2,十六进制的0x000C,根据一个字节表示两位十六进制,所以0x000C需要两个字节来表示
  • lengthAdjustment =0 ,无需调整,在当前例子中需要全部读取,不需要额外增加和减少
  • initialBytesToStrip = 0 解码过程中,也不需要丢弃任何数据

4 示例二

Netty通信中的粘包半包问题(六),Netty,java,服务器
数据包大小: 14B = 长度域2B + “HELLO, WORLD”
长度域的值为12B(0x000C),解码后,希望丢弃长度域2B字段,所以下方参数设置应为:

  • lengthFieldOffset=0 长度域前面没有其他数据,不需要设置偏移量
  • lengthFieldLength = 2 0x000C十六进制占用两个字节
  • lengthAdjustment = 0 长度值也不需要调整,因为长度域本身的值和报文长度的值是相等的
  • initialBytesToStrip = 2 解码过程中,需要丢弃2个字节的数据

5.示例三

Netty通信中的粘包半包问题(六),Netty,java,服务器
数据包大小: 14B = 长度域2B + “HELLO, WORLD”,长度域的值为14(0x000E),包含了长度域本身的长度,希望解码后保持一样,参数设置如下:

  • lengthFieldOffset = 0,长度域偏移量前面没有任何数据,不需要设置
  • lengthFieldLength = 2 0x000E,根据一个字节等于两位十六进制的换算,所以占2个字节
  • lengthAdjustment = -2, 因为长度域为14(0x000E),而报文内容为12,为了防止读取报文超出报文本体,将和长度字段一起读取进来,需要告诉Netty,实际读取的报文长度比长度域中的要少2(12-14=-2)
  • initialBytesToStrip = 0,解码过程中没有丢弃任何数据

6 示例四

Netty通信中的粘包半包问题(六),Netty,java,服务器
在长度域前添加2个字节的Header,长度域的值(0x00000C)=12,总数据包长度:17 = Header(2B) + 长度域(3B) + “HELLO, WORLD”
长度域的值为12B(0x00000C),编码解码后,长度保持一直,所以参数设置应为

  • lengthFieldOffset = 2,由于长度域前面有2个字节的Header,所以需要跳过两个字节才是长度域
  • lengthFieldLength = 3, 0x00000C,根据1个字节等于两位十六进制数
  • lengthAdjustment = 0 无需修正长度,因为长度域本身的值和报文长度的值是相等的
  • initialBytesToStrip = 0 在解码过程没有丢弃任何数据

7 示例五

Netty通信中的粘包半包问题(六),Netty,java,服务器
带有两个Header.HDR1 丢弃,长度域丢弃,只剩下第二个Header和有效包体,这种协议中,一般HDR1 可以表示magicNumber,表示应用只接受该magicNumber开头的二进制数据,RPC里面用的比较多,总数据包长度:16 = HDR1(1B) + 长度域(2B) + HDR2(1B) + “HELLO, WORLD”
长度域的值为12B(0x000C),参数应设置为

  • lengthFieldOffset = 1 表示长度域前面需要跳过HDR1的长度,才是长度域的数据
  • lengthFieldLength = 2 根据十六进制与字节的换算单位,两个十六进制数等于1个字节,所以0x000C占用2个字节
  • lengthAdjustment = 1 因为长度域的值为12,报文内容为12,到那时我们需要把HDR2的值一起读取进来,需要告诉Netty,实际读取的报文内容比长度域中的要多1(12 +1 =13)
  • initialBytesToStrip = 3 丢弃了HDR1和长度域(1 + 2 = 3)

8. 示例6

Netty通信中的粘包半包问题(六),Netty,java,服务器
带有两个Header,HDR1丢弃,长度域也丢弃,只剩下第二个header和有效包体,总数据包长度:16 = HDR(1B) + 长度域(2B) + HDR2(1B) + “HELLO, WORLD”
参数设置如下:

  • lengthFieldOffset = 1 长度域的偏移量为1,需要跳过HDR1才能读取到长度域
  • lengthFieldLength = 2 根据十六进制与字节的换算单位,两个十六进制数等于1个字节,所以0x0010 占用2个字节
  • lengthAdjustment = -3 因为长度域为16,需要告诉Netty,实际读取的报文内容长度比实际需要读取的报文长度要少3(13 - 16 = -3),因为需要读取到HDR2(1B) + “HELLO, WORLD”(12B)
  • initialBytesToStrip = 3 丢弃了HDR1和长度域字段

9.总结

LengthFieldBasedFrameDecoder中的参数相比之前的特殊字符、固定长度、特殊分隔符的解决方案复杂度上升了不少,但是这却是最优的解决方案,具体业务还要具体分析,有的业务场景可能不需要消息头+消息体这种方案,毕竟这种方案稍有不慎就会出错,参数设置也比较多,需要每个参数都熟悉才能开发业务,相信以后可能会有更好的方案文章来源地址https://www.toymoban.com/news/detail-816041.html

到了这里,关于Netty通信中的粘包半包问题(六)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 「 计算机网络 」TCP的粘包拆包问题

    参考鸣谢 大病初愈,一分钟看懂TCP粘包拆包 雷小帅 TCP 的粘包拆包以及解决方案 一乐说 当我们在进行网络传输时,由于各种原因,数据包的发送和接收可能会出现粘包和拆包的问题。粘包和拆包都是数据分组错误的情况,其中粘包指的是多个数据包被合并成一个,而拆包则

    2024年02月01日
    浏览(39)
  • 【计网】一起聊聊TCP的粘包拆包问题吧

    在TCP中,粘包和拆包问题是十分常见的,如 基于TCP协议 的RPC框架、Netty等。 粘包(Packet Stickiness) 指的是在网络通信中,发送方连续发送的多个小数据包被接收方一次性接收的现象。这可能是因为底层传输层协议(如TCP)会将 多个小数据包合并成一个大的数据块 进行传输,导

    2024年04月12日
    浏览(36)
  • 说说 TCP的粘包、拆包

    拆包和粘包是在socket编程中经常出现的情况, 在socket通讯过程中,如果通讯的一端一次性连续发送多条数据包,tcp协议会将 多个数据包打包 成一个tcp报文发送出去,这就是所谓的 粘包 。 如果通讯的一端发送的数据包超过一次tcp报文所能传输的最大值时,就会将 一个数据包

    2024年02月09日
    浏览(50)
  • TCP的粘包、拆包、解决方案以及Go语言实现

    TCP的粘包和拆包问题往往出现在基于TCP协议的通讯中,比如RPC框架 在使用TCP进行数据传输时,由于TCP是基于字节流的协议,而不是基于消息的协议,可能会出现粘包(多个消息粘在一起)和拆包(一个消息被拆分成多个部分)的问题。这些问题可能会导致数据解析错误或数据

    2024年02月15日
    浏览(84)
  • 聊聊TCP协议的粘包、拆包以及http是如何解决的?

    目录 一、粘包与拆包是什么? 二、粘包与拆包为什么发生? 三、遇到粘包、拆包怎么办? 解决方案1:固定数据大小 解决方案2:自定义请求协议 解决方案3:特殊字符结尾  四、HTTP如何解决粘包问题的? 4.1、读取请求行/请求头、响应行/响应头 4.2、 怎么读取body数据呢?

    2024年02月11日
    浏览(45)
  • Netty-LengthFieldBasedFrameDecoder-解决拆包粘包问题的解码器

    maxFrameLength:指定解码器所能处理的数据包的最大长度,超过该长度则抛出 TooLongFrameException 异常; lengthFieldOffset:指定 长度字段 的起始位置; lengthFieldLength:指定 长度字段 的长度:目前支持1(byte)、2(short)、3(3个byte)、4(int)、8(Long) lengthAdjustment:指定 长度字段 所表示的消息

    2024年02月12日
    浏览(40)
  • Netty编解码器,Netty自定义编解码器解决粘包拆包问题,Netty编解码器的执行过程详解

    当Netty发送或者接收一个消息的时候,就会发生一次数据转换。入站消息会被解码(从字节转换为另一种格式,比如java对象);出站消息会被编码成字节。 Netty 提供一系列实用的编解码器,他们都实现了 ChannelInboundHadnler 或者 ChannelOutboundHandler 接口。在这些类中,channelRead 方

    2023年04月23日
    浏览(45)
  • Netty粘包与拆包

    文章首发地址 TCP是一个“流”协议。所谓流,就是没有界限的一长串二进制数据。 拆包和粘包 :TCP作为传输层协议,并不了解上层业务数据的具体含义,它会根据TCP缓冲区的实际情况进行数据包的划分,所以在业务上认为是一个完整包的,可能会被TCP拆分成多个包进行发送

    2024年02月16日
    浏览(34)
  • 死磕GMSSL通信-java/Netty系列(三)

    死磕GMSSL通信-java/Netty系列(三) 接着上次的博客继续完善,上次其实只是客户端的改造,这次把服务端的也补上,netty集成GMSSL实现GMServer 1、netty_tcnative c代码改造,这个是客户端和服务端都需要都该的地方 sslcontext.c文件 TCN_IMPLEMENT_CALL(jlong, SSLContext, make)(TCN_STDARGS, jint protoc

    2024年04月26日
    浏览(27)
  • Netty通信在中间件组件中的广泛使用-Dubbo3举例

    Netty是一个高性能异步IO通信框架,封装了NIO,对各种bug做了很好的优化解决。所以很多中间件底层的通信都会使用Netty,比如说:Dubbo3,rocketmq,ElasticSearch等。 比方说,我们使用dubbo作为rpc跨进程远程通信,其实底层使用的还是Netty客户端与服务端的交互。我们封装好dubbo,然

    2024年02月07日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包