博客
关于我
Netty源码—8.编解码原理一
阅读量:789 次
发布时间:2023-02-15

本文共 1700 字,大约阅读时间需要 5 分钟。

Netty数据读取与解码入门

1. 读数据入口

当客户端Channel的Reactor线程NioEventLoop检测到有读事件时,会执行NioByteUnsafe的read()方法。该方法会调用doReadBytes()方法将TCP缓冲区的数据读到由ByteBufAllocator分配的一个ByteBuf对象中,然后通过pipeline.fireChannelRead()方法带上这个ByteBuf对象向下传播ChannelRead事件。

在传播过程中,首先会来到pipeline的head结点的channelRead()方法。该方法会继续带着那个ByteBuf对象向下传播ChannelRead事件,比如会来到ByteToMessageDecoder结点的channelRead()方法。

需要注意的是,服务端Channel的unsafe变量是一个NioMessageUnsafe对象,而客户端Channel的unsafe变量是一个NioByteUnsafe对象。

2. 拆包原理

不用Netty的拆包原理

不断地从TCP缓冲区中读取数据,每次读完都判断是否为一个完整的数据包。如果当前读取的数据不足以拼接成一个完整的数据包,就保留数据,继续从TCP缓冲区中读。如果当前读取的数据加上已读取的数据足够拼成完整的数据包,就将拼好的数据包往业务传递,而多余的数据则保留。

Netty的拆包原理

Netty拆包基类内部会有一个字节容器,每次读取到数据就添加到字节容器中。然后尝试对累加的字节数据进行拆包,拆成一个完整的业务数据包,这个拆包基类叫ByteToMessageDecoder。

3. ByteToMessageDecoder解码步骤

(1) 解码的整体步骤

(2) 首先累加字节流

如果当前字节容器中没有数据,那么就将字节容器的指针指向新读取的数据。如果当前字节容器中有数据,那么就调用累加器的cumulate()方法将数据累加到字节容器。

(3) 然后调用子类的decode()方法进行解析

把累加字节容器里的字节流通过子类的decode()方法进行解析。

(4) 接着清理字节容器

为了防止发送端发送数据过快,ByteToMessageDecoder会在读取完一次数据并完成业务拆包后,清理字节容器。

(5) 最后将解析到的ByteBuf向下传播

如果调用子类的decode()方法可以解析到一个ByteBuf对象,则将这个ByteBuf对象向下传播。

4. 解码器抽象的解码过程总结

解码过程是通过一个叫ByteToMessageDecoder的抽象解码器来实现的,ByteToMessageDecoder实现的解码过程分为如下四步:

(1) 累加字节流

也就是把当前读到的字节流累加到一个字节容器里。

(2) 调用子类的decode()方法进行解析

ByteToMessageDecoder的decode()方法是一个抽象方法,不同种类的解码器会有自己的decode()方法逻辑。

(3) 清理字节容器

为了防止发送端发送数据过快,ByteToMessageDecoder会在读取完一次数据并完成业务拆包后,清理字节容器。

(4) 传播已解码的业务数据包

如果List列表里有解析出来的业务数据包,那么就通过pipeline的事件传播机制往下进行传播。

5. Netty里常见的开箱即用的解码器

(1) 基于固定长度解码器

判断当前字节容器可读字节是否小于固定长度。

(2) 基于行分隔符解码器

基于行分隔符的拆包器可以同时处理\n和\r\n两种类型的行分隔符,其处理逻辑分为非丢弃模式和丢弃模式、找到行分隔符和未找到行分隔符的情况。

(3) 基于分隔符解码器

可以向基于分隔符解码器DelimiterBasedFrameDecoder传递一个分隔符列表,这样该解码器就会按照分隔符列表对数据包进行拆分。

(4) 基于长度域解码器

主要的逻辑步骤如下:

(1) 丢弃模式的处理

(2) 获取待拆数据包的大小

(3) 对数据包进行长度校验

(4) 跳过指定字节长度

(5) 抽取数据包

转载地址:http://xvcfk.baihongyu.com/

你可能感兴趣的文章
Navicat向sqlserver中插入数据时提示:当 IDENTITY_INSERT 设置为 OFF 时,不能向表中的标识列插入显式值
查看>>
Navicat因导入的sql文件中时间数据类型有参数而报错的原因(例:datetime(3))
查看>>
Navicat如何连接MySQL
查看>>
navicat导入.sql文件出错2006- MySQLserver has gone away
查看>>
Navicat工具Oracle数据库复制 or 备用、恢复功能(评论都在谈论需要教)
查看>>
navicat怎么导出和导入数据表
查看>>
Navicat报错:1045-Access denied for user root@localhost(using passwordYES)
查看>>
Navicat控制mysql用户权限
查看>>
Navicat通过存储过程批量插入mysql数据
查看>>
Navicat(数据库可视化操作软件)安装、配置、测试
查看>>
NB-IOT使用LWM2M移动onenet基础通信套件对接之APN设置
查看>>
NBear简介与使用图解
查看>>
nc命令详解
查看>>
ndk特定版本下载
查看>>
NDK编译错误expected specifier-qualifier-list before...
查看>>
Neat Stuff to Do in List Controls Using Custom Draw
查看>>
Necurs僵尸网络攻击美国金融机构 利用Trickbot银行木马窃取账户信息和欺诈
查看>>
NeHe OpenGL教程 07 纹理过滤、应用光照
查看>>
NeHe OpenGL教程 第四十四课:3D光晕
查看>>
Neighbor2Neighbor 开源项目教程
查看>>