转载

Netty如何解决粘包拆包?(二)

Netty如何解决粘包拆包?(二)

前言

TCP是个流协议,所谓流,就是没有界限的一串数据。大家可以想想河里的流水,是连成一片的,其间并没有分界线。TCP底层并不了解上层业务数据的具体含义,它会根据TCP缓冲区的实际情况进行包的划分,所以在业务上认为,一个完整的包可能会被TCP拆分成多个包进行发送,也有可能把多个小的包封装成一个大的数据包发送,这就是所谓的TCP粘包和拆包问题。

案例:

Netty如何解决粘包拆包?(二)

某时刻发送端缓冲区过小,导致ABC数据包发生拆包成AB、C,拆分出来的C与数据包DEF粘包发送给接收端。

拆包场景:

(1)要发送的数据大于缓冲区剩余大小;

(2)待发送的数据大于MSS,TCP会在传输前将其拆分;

粘包场景:

(1)要发送小于缓冲区剩余大小;

(2)接受数据端的应用层没来得及读取缓冲区的数据;

应用层协议存在粘包拆包情况,netty如何利用Frameecoder来解决的?

在Netty的codec模块中,对通用传输协议提供了支持,并且在FrameDecoder中对于粘包拆包给出了通用的解决方案,应用层协议解析类可以通过继承它而无须担心粘包、拆包等问题。

Netty如何解决粘包拆包?(二)

可以看到http协议解析类HttpMessageDecoder固定、长度解析类FixedLengthFrameDecoder、换行协议解析类LineBaseFrameDecoder等等都是基于FrameDecoder拓展实现,而FrameDecoder继承自SimpleChannelUpstreamHandler,是不是有点熟悉呢?没错,这个在 解读netty3.9的数据处理流程(一) 的处理执行者,没看过的同学可以点进去看看。

拨开浓雾:

对于脉络我们已经梳理清晰,拆包粘包是前文数据处理流程的某一个环节,那到底FrameDecoder为什么那么神奇,能通用地处理粘包呢?可以想象,仓库包裹打包出库场景,打包人员在工作台打包货物,直到缺少货物再让拣选员拣选过来接着打包,缺货的时候是不是还有商品在工作台上,是不是有点懂了FrameDecoder在做什么事呢?可以理解就是一个打包工作台,还没法打包就等待但是注意货物还在台上,可以打包就一直打包下去即可。

那我们来看看FrameDecoder庐山真面目。

Netty如何解决粘包拆包?(二)

可以看到cumulation不为空的情况下,就调用appendToCumulation将接受到的数据塞到cumulation中,cumulation就是刚刚货物打包场景中的工作台,否则就调用callDecode循环地去解析应用数据包,并且调用updateCumulation订正cumulation的数据。

Netty如何解决粘包拆包?(二)

当cumulation可读时,记录下旧的读指针用于对比,并调用实际的协议执行者解析出应用层数据包。

1、如果数据包为空并且读指针未挪动,说明应用层数据包不全,跳出等待数据;

2、如果数据包为空但是读指针挪动,抛弃部分数据可能正在读,继续调用解析;

3、如果存在数据包并且读指针未移动,则抛出异常;

4、如果数据包不为空并且读指针挪动,很明显继续调用解析;

喜欢的读者可以关注路上小栈,及时获取最新的技术文章,专注源码分析、技术业务思考等。

Netty如何解决粘包拆包?(二)

原文  https://juejin.im/post/5cc937e36fb9a032086ddbcc
正文到此结束
Loading...