佛教中除不听各种淫邪声音之外,更不可听别人的秘密。因他论耳根最到家,故取挖耳之形,以示耳根清净。
来看看netty的核心组件解码器Decoder
- Decoder的作用
- 半包,粘包问题
- 从模板和装饰器模式看Decoder解码原理
1.Decoder作用
最根本的就是将网络中的二进制数据,解析成为目标对象(Object)。

抽象出来本质就是上图,其它任何动作都是在完成这个目的。
对吧,学习一定要抓住本质。
先来看看网络数据再网络和操作系统底层是怎么传输的:
a.网络数据是以二进制的数据包进行传输的,在netty中是以bytefuf数据包进行传递。这个概念之 后 章节会讲到。
b.会涉及tcp/ipc传输协议。
先来看看TCP/IP协议的数据封装和分用过程,大致如下图所示:

可以看到没往下传输一层,会加上一个每层的首部。这个可以理解为,唐僧西天取经的过程中,通关文牒都要盖一个章一样。不加这个人家不认你。用的时候在解析出来报文体。
这里就不得不提一个概念MSS(TCP[数据包]每次能够传输的最大数据分段)
后面在传输过程中,超过这个值,数据包会进行拆分;小于这个值,数据包会进行合并。
c.dma复制
简单讲 就是绕过cpu,直接操作内存在设备间传输数据。
具体流程如下:

dam传输数据时,cpu不参与,dma处理完之后通知cpu进行后续处理。
理解这几个点之后,我们再来看一看正真的数据传播流程:
1.首先发送端,在用户缓存区里的bytebuf数据包会进行一次cpu复制;
2.cpu复制之后数据会缓存在发送缓冲区的内核空间里,这时候数据是完整的;
3.内核缓冲区进行一次DMA复制,数据被写入网卡设备中,此时网卡里面的数据包会进行重组;
4.写入网卡的数据通过TCP/IP协议进行传输,组装成新的二进制数据包,有最大数据限制;
5.接收端通过TCP/IP协议接收到二进制数据包,此时数据是完整的;
6.接收端在内核缓冲区进行一次DMA复制,形成新的bytebuf数据包;
7.接收端进行一次cpu复制,bytebuf数据包被写入用户缓冲区。
具体流程如下图:

这个过程会涉及两次分割二进制包:
a.传输过程中的分割;
b.系统复制过程中的分割;
所以粘包,和半包问题的出现就发生在这两个过程中,数据包少了,多个合在一起就会造成粘包。数据包多了,就会进行分割,分割就会打破原来的数据结构,出现半包问题。
来看看netty Decoder是怎么解决这个问题的
1.通过ByteToMessageDecoder 将二进制数据转换成对象
2.通过MessageToMessageDecoder将对象数据转换成对象

先来看看ByteToMessageDecoder 它是一个基类,主要使用模板方法接受管理bytebuf,子类通过实现钩子方法,处理业务逻辑,处理完业务逻辑将写入List<Object>中,之后在流水线上发送到下一站。流水线概念会在之后一章单独讲解。
public class Byte2IntegerDecoder extends ByteToMessageDecoder {
//钩子实现
@Override
public void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {
while (in.readableBytes() >= 4) {
Integer anInt = in.readInt();
Logger.info("解码出一个整数: " + anInt);
out.add(anInt);
}
}
}
来看看它的具体使用,继承ByteToMessageDecoder,钩子方法里实现业务逻辑。
回顾一下什么是模板方法:
核心点:抽象类会实现一系列公共方法共子类使用。

1.抽象类会定义一系列的模板方法,子类自动继承。
2.子类通过钩子方法处理具体业务逻辑。
好,我们再看一个它的核心子类ReplayingDecoder(回放解码器)。
什么是回放呢?
我们读取数据的时候是在操作一个二进制数组,数组元素完整的话,指针移动没有问题。但是数据元素不完整,再次读取的时候记数指针会回到开头重新执行。
netty通过checkpoint指针来完成指针回放

最低0.47元/天 解锁文章
546

被折叠的 条评论
为什么被折叠?



