【图解IO与Netty系列】Netty编解码器、TCP粘包拆包问题处理、Netty心跳检测机制

Netty编解码器、TCP粘包拆包问题处理、Netty心跳检测机制

  • Netty编解码器
    • 编码器
    • 解码器
    • 编解码器
    • Netty提供的现成编解码器
  • TCP粘包拆包问题处理
  • Netty心跳检测机制

Netty编解码器

网络传输是以字节流的形式传输的,而我们的应用程序一般不会直接对字节流进行处理,而是把字节流解析成有一定结构的数据格式再去处理。因此我们在发送数据时,要对我们的数据进行编码,把它转换成二进制字节流的形式,然后在网络中进行传输,当我们接收到对方传输过来的二进制字节流时,又需要对其进行解码,解析成应用程序能够处理的数据格式。

比如客户端向服务端发送数据的场景:
在这里插入图片描述

这个编码和解码的动作,可以由用户自己去实现,比如我们使用Java原生的NIO进行开发时,就不得不自己去实现一套编解码的逻辑。而我们使用了Netty之后,Netty给我们封装好了各种编解码器,我们只要使用对应的编解码器,即可以很简单的对数据进行编解码,进一步简化了网络程序的开发。

在这里插入图片描述

编码器

Netty提供了两个编码器抽象类,我们可以选择性的继承它们以实现自己定制的编码器,这两个编码器抽象类分别是MessageToByteEncoder和MessageToMessageEncoder。

  • MessageToByteEncoder<I>:将消息编码为字节
  • MessageToMessageEncoder<T>:将消息编码为消息

它们都继承了ChannelOutboundHandlerAdapter,因此它们都是用于处理出站事件的。

在这里插入图片描述

MessageToByteEncoder的抽象方法encode(ChannelHandlerContext ctx, I msg, ByteBuf out)把特定的类型的消息msg编码成二进制,消息类型由泛型“I”指定。我们继承MessageToByteEncoder后,要实现这个encode方法,encode方法接收指定类型的消息对象msg,然后我们对其进行编码后要放入到ByteBuf类型的out对象中。

在这里插入图片描述

MessageToMessageEncoder的抽象方法encode(ChannelHandlerContext ctx, I msg, ByteBuf out)把特定的类型的消息msg编码成另外一种消息,消息类型由泛型“I”指定。我们继承MessageToMessageEncoder后,要实现这个encode方法,encode方法接收指定类型的消息对象msg,然后我们对其进行编码后要放入到List类型的out对象中。

在这里插入图片描述

比如我们可以通过MessageToMessageEncoder把一个对象转换成json格式的字符串,然后通过MessageToByteEncoder把json字符串加密后编码成二进制字节流。

在这里插入图片描述

解码器

Netty提供了两个解码器抽象类,我们可以选择性的继承它们以实现自己定制的解码器,这两个解码器抽象类分别是ByteToMessageDecoder和MessageToMessageDecoder<I>。

  • ByteToMessageDecoder:将字节解码为消息
  • MessageToMessageDecoder<I>:将一种消息类型解码为另一种

它们都继承了ChannelInboundHandlerAdapter,因此它们都是用来处理入站事件的。

在这里插入图片描述

ByteToMessageDecoder的抽象decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out)方法中ByteBuf类型参数in可以获取到接收进来的字节流,我们需要把它解码成特定的对象,然后放入List类型的out中。

在这里插入图片描述

MessageToMessageDecoder中的抽象方法decode(ChannelHandlerContext ctx, I msg, List<Object> out)把特定类型的对象msg解码成另一种类型的对象,然后放入out中。

在这里插入图片描述

比如我们接收到上面这个例子发送的编码后的二进制字节流,我们可以通过ByteToMessageDecoder解码后解密成json字符串,然后通过MessageToMessageDecoder把json字符串转成对象。

在这里插入图片描述

编解码器

Netty还提供了集编码解码一体的编解码器抽象类,它们分别是ByteToMessageCodec和MessageToMessageCodec,它们同时处理入站事件和出站事件。但是我们一般很少使用,更多的是把编码和解码分开两个类,这样才能最大化代码的可重用性和可扩展性。

Netty提供的现成编解码器

上面这些都是抽象类,是需要我们自己继承后实现编解码逻辑的,而Netty还有更牛逼的直接现成的编解码器类提供给我们,我们把它们组装到ChannelPipeline中即可使用。

在这里插入图片描述

根据不同的协议或不同的功能,Netty提供了对应的编码器或解码器,有处理SSL或TLS协议的、有处理HTTP协议的、有做HTTP压缩的、有处理WebSocket协议的等等。这里就不一一细说了,我们只要知道Netty都提供了哪些功能的内置编解码器,再按需的去了解即可。

TCP粘包拆包问题处理

由于TCP是一个面向二进制流的协议,是传输层协议,并不理解应用层传下来的业务数据,但是TCP又会根据MSS对数据进行分包处理,于是会出现下面四种情况:

在这里插入图片描述

  • 第一种情况是TCP分包分的刚刚好,D1和D2两个独立的数据包分开发送,这是没有问题的。
  • 第二种情况就是TCP把D1和D2两个数据包连在一起被TCP一同发送,此时就发生了粘包问题。
  • 第三种情况和第四种情况都是其中一个数据包被分成了两半,与另一个数据包一起一同发送,此时就发生了拆包问题。

当发生TCP粘包拆包问题时,接收数据的一方需要通过某种机制将被拆分或粘连的数据包还原成独立的数据包。

Netty提供了多个解码器可以处理TCP粘包拆包问题:

  • LineBasedFrameDecoder:利用回车换行符做分包处理
  • DelimiterBasedFrameDecoder:利用指定的特殊分隔符做分包处理
  • FixedLengthFrameDecoder:以固定长度来分包
  • LengthFieldBasedFrameDecoder:消息头中记录消息总长度,通过消息头中记录的消息体长度进行分包

这几个都是上面说过的Netty提供的现成解码器。

除此以外我们还可以自己实现TCP粘包拆包的处理:

  1. 我们可以通过实现自己的MessageToByteEncoder将消息编码成二进制时,先写出消息长度再写出消息体
  2. 然后实现ByteToMessageDecoder(或ReplayingDecoder),在解码时先读取一个int,得到消息体长度,然后再读取指定长度的字节流解码成出消息体。

在这里插入图片描述

Netty心跳检测机制

Netty提供了一个IdleStateHandler可以用于进行心跳检测,我们可以设置读超时时间或写超时时间,比如我们设置了读超时时间,IdleStateHandler在指定时间内没有从通道中读取到数据,就会触发一个IdleStateEvent事件,IdleStateEvent中有一个state字段记录是什么类型的超时时间(读超时、写超时、读写超时)。

我们可以在ChannelPipeline添加一个IdleStateHandler,然后我们再继承SimpleChannelInboundHandler实现自定义的入站处理放于IdleStateHandler的后面,就可以在发生读超时或写超时事件时,在userEventTriggered(ChannelHandlerContext ctx, Object evt)方法中接收到IdleStateHandler发出的IdleStateEvent对象,我们就可以进行相应处理,比如读超时事件则进行探活处理或者关闭连接等操作。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/28470.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Verilog-Behavior Level 和 RTL Level 和 GATE Level的区别

硬件设计中对硬件的描述可以具有不同的抽象级别&#xff0c;以Verilog为例&#xff1a; Behavior Level。描述的是硬件的行为&#xff0c;当我们在看到如下关键字时就是行为级别的代码&#xff1a;#&#xff0c;wait&#xff0c;while&#xff0c;force&#xff0c;release等&…

System-Verilog 实现DE2-115 流水灯

文章目录 一、什么是SystemVerilog二、代码实现实现结果 一、什么是SystemVerilog SystemVerilog是一种硬件描述语言(HDL)&#xff0c;它用于设计和验证电子系统&#xff0c;特别是在集成电路(IC)和系统级芯片(SoC)的设计过程中。SystemVerilog是Verilog语言的一个超集&#xf…

大模型生成的常见Top-k、Top-p、Temperature参数

参考&#xff1a; https://zhuanlan.zhihu.com/p/669661536 topK&#xff0c;topP https://www.douyin.com/video/7380126984573127945 主要是softmax产生的词表每个词的概率分布后&#xff0c; topK&#xff0c;比如K3&#xff0c;表示采样概率最大的前3个&#xff0c;其他全…

【Perl】与【Excel】

引言 perl脚本语言对于文本的处理、转换很强大。对于一些信息量庞大的文本文件&#xff0c;看起来不直观&#xff0c;可以将信息提取至excel表格中&#xff0c;增加数据分析的可视化。perl语言的cpan提供了大量模块。对于excel文件的操作主要用到模块&#xff1a; Spreadshee…

【C++】类相关知识

C 类相关内容 1 默认构造 在C中&#xff0c;如果你遇到了错误信息“the default constructor of ‘B’ cannot be referenced – it is a deleted function”&#xff0c;这通常意味着类B的默认构造函数&#xff08;即不带参数的构造函数&#xff09;被声明为 delete了&#…

C 运算符优先级

在 C 语言中&#xff0c;运算符的优先级决定了在表达式中运算符的计算顺序。以下是 C 语言中运算符优先级表&#xff0c;按从高到低的顺序排列&#xff1a; 1. **括号**: () 2. **后缀运算符**: [] (数组下标), () (函数调用), . (成员访问), -> (指向成员访问), (后缀自…

详解 HBase 的安装部署及命令行操作

一、下载安装 进入 HBase 下载地址&#xff1a;https://archive.apache.org/dist/hbase/ 下载对应版本的 HBase 安装包并上传到虚拟机&#xff0c;并确保安装了 jdk 环境 将 HBase 安装包解压 #在 /opt/software 目录下解压安装包 tar -zxvf hbase-1.3.1-bin.tar.gz -C /opt/…

Android的自启动

最近要用到这个&#xff0c;所以也花时间看看。 从分层来说&#xff0c;安卓的自启动也分成三种&#xff0c;app的自启动&#xff0c;framework服务的自启动&#xff0c;HAL服务的自启动。现在简单说说这三种吧。当然&#xff0c;我主要关注的还是最后一种。。。 一 App的自启…

【论文速读,找找启发点】2024/6/16

ICME 2023 End-To-End Part-Level Action Parsing With Transformer 类似 DETR&#xff0c;通过 加 query的方式实现 端到端 ELAN: Enhancing Temporal Action Detection with Location Awareness 如何实现位置感知&#xff1f; > 重叠的卷积核&#xff1f; Do we really …

大数据开发流程解析

大数据开发是一个复杂且系统的过程&#xff0c;涉及需求分析、数据探查、指标管理、模型设计、ETL开发、数据验证、任务调度以及上线管理等多个阶段。本文将详细介绍每个阶段的内容&#xff0c;并提供相关示例和代码示例&#xff0c;帮助理解和实施大数据开发流程。 本文中的示…

基于WPF技术的换热站智能监控系统02--标题栏实现

1、布局划分 2、准备图片资源 3、界面UI控件 4、窗体拖动和关闭 5、运行效果 走过路过不要错过&#xff0c;点赞关注收藏又圈粉&#xff0c;共同致富&#xff0c;为财务自由作出贡献

CodeQL从入门到入土

为什么在现在写这文章 CodeQL传闻找到了Log4j的漏洞&#xff0c;这段时间上边要求&#xff0c;把公司系统内部常见的问题用CodeQL写检测脚本&#xff0c;用于系统长期检测。主要是记录这段时间的学习&#xff0c;以及自己总结的常用写法。 一个需求&#xff0c;不同人写出来的…

【Go语言】Gin 框架教程

Gin 框架教程 1.第一个 Gin 程序 1.1 Gin 安装 # 执行执行如下操作即可&#xff0c;安装Gin前需要安装Go环境 go get -u -v github.com/gin-gonic/gin # -v&#xff1a;打印出被构建的代码包的名字 # -u&#xff1a;已存在相关的代码包&#xff0c;强行更新代码包及其依赖包…

写点什么吧,作为STM32系列的开篇……

自从本科毕业后&#xff0c;就再也没碰过单片机…… 自从研究生毕业后&#xff0c;就再也没碰过硬件…… 自以为以前单片机玩的熟得很&#xff0c;特别是ATMEGA系列的AVR单片机&#xff0c;由于老师的推荐&#xff0c;本科时花了好多精力在这个系列单片机上面…… 本科时STM…

框架的使用

什么是框架&#xff1f; 盖房子&#xff0c;框架结构 框架结构就是房子主体&#xff0c;基本功能 把很多基础功能已经实现&#xff08;封装了&#xff09; 框架&#xff1a;在基础语言之上&#xff0c;对各种基础功能进行封装&#xff0c;方便开发者&#xff0c;提高开发效…

JavaFX 图像视图

JavaFX ImageView 控件可以在 JavaFX GUI 中显示图像。ImageView 控件必须添加到场景图中才能可见。JavaFX ImageView 控件由类表示 javafx.scene.image.ImageView。 创建一个 ImageView 通过创建类的实例来创建 ImageView 控件实例ImageView。类的构造函数ImageView需要一个…

02 设计过程概述

02 设计过程概述 2-1 设计需求2-2 飞机设计的各个阶段2-2-1 概念设计2-2-2 初步设计2-2-3 详细设计 2-3 飞机概念设计的流程2-4 集成产品开发和飞机设计2-5 补充2-5-1 布局设计&#xff08;Configuration Design&#xff09;关键任务&#xff1a;作用和重要性&#xff1a;使用领…

设置systemctl 启动PostgreSQL

1、在/etc/systemd/system目录下&#xff0c;新建配置文件 postgresql.service vi /etc/systemd/system/postgresql.service [Unit] # 简短描述 Descriptionpostgresql.service # 在network.target服务之后运行&#xff0c;这里可以不要 Afternetwork.target [Service] Type…

ARIMA模型与ARIMA-GARCH模型预测时间序列

上世纪 70 年代初&#xff0c;Ljung 等人提出 ARIMA 模型&#xff0c;又称求和自回归移动平均模型。其思想 是针对于非平稳时间序列进行数学建模&#xff0c;将其通过差分运算后 进行相关数据刻画 &#xff0c;变为一个平稳的新序列&#xff0c;进而进行相关数据的刻画。 自 1…

Sping源码(九)—— Bean的初始化(非懒加载)— Bean的创建方式(自定义BeanPostProcessor)

序言 之前文章有介绍采用FactoryBean的方式创建对象&#xff0c;以及使用反射创建对象。 这篇文章继续介绍Spring中创建Bean的形式之一——自定义BeanPostProcessor。 之前在介绍BeanPostProcessor的文章中有提到&#xff0c;BeanPostProcessor接口的实现中有一个Instantiatio…