前言
TCP是个流协议,所谓流,就是没有界限的一串数据。大家可以想想河里的流水,是连成一片的,其间并没有分界线。TCP底层并不了解上层业务数据的具体含义,它会根据TCP缓冲区的实际情况进行包的划分,所以在业务上认为,一个完整的包可能会被TCP拆分成多个包进行发送,也有可能把多个小的包封装成一个大的数据包发送,这就是所谓的TCP粘包和拆包问题。
案例:
某时刻发送端缓冲区过小,导致ABC数据包发生拆包成AB、C,拆分出来的C与数据包DEF粘包发送给接收端。
拆包场景:
(1)要发送的数据大于缓冲区剩余大小;
(2)待发送的数据大于MSS,TCP会在传输前将其拆分;
粘包场景:
(1)要发送小于缓冲区剩余大小;
(2)接受数据端的应用层没来得及读取缓冲区的数据;
应用层协议存在粘包拆包情况,netty如何利用Frameecoder来解决的?
在Netty的codec模块中,对通用传输协议提供了支持,并且在FrameDecoder中对于粘包拆包给出了通用的解决方案,应用层协议解析类可以通过继承它而无须担心粘包、拆包等问题。
可以看到http协议解析类HttpMessageDecoder固定、长度解析类FixedLengthFrameDecoder、换行协议解析类LineBaseFrameDecoder等等都是基于FrameDecoder拓展实现,而FrameDecoder继承自SimpleChannelUpstreamHandler,是不是有点熟悉呢?没错,这个在 解读netty3.9的数据处理流程(一) 的处理执行者,没看过的同学可以点进去看看。
拨开浓雾:
对于脉络我们已经梳理清晰,拆包粘包是前文数据处理流程的某一个环节,那到底FrameDecoder为什么那么神奇,能通用地处理粘包呢?可以想象,仓库包裹打包出库场景,打包人员在工作台打包货物,直到缺少货物再让拣选员拣选过来接着打包,缺货的时候是不是还有商品在工作台上,是不是有点懂了FrameDecoder在做什么事呢?可以理解就是一个打包工作台,还没法打包就等待但是注意货物还在台上,可以打包就一直打包下去即可。
那我们来看看FrameDecoder庐山真面目。
可以看到cumulation不为空的情况下,就调用appendToCumulation将接受到的数据塞到cumulation中,cumulation就是刚刚货物打包场景中的工作台,否则就调用callDecode循环地去解析应用数据包,并且调用updateCumulation订正cumulation的数据。
当cumulation可读时,记录下旧的读指针用于对比,并调用实际的协议执行者解析出应用层数据包。
1、如果数据包为空并且读指针未挪动,说明应用层数据包不全,跳出等待数据;
2、如果数据包为空但是读指针挪动,抛弃部分数据可能正在读,继续调用解析;
3、如果存在数据包并且读指针未移动,则抛出异常;
4、如果数据包不为空并且读指针挪动,很明显继续调用解析;
喜欢的读者可以关注路上小栈,及时获取最新的技术文章,专注源码分析、技术业务思考等。
以上所述就是小编给大家介绍的《Netty如何解决粘包拆包?(二)》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- Hadoop小文件解决方案-基于文件整合的解决方案
- scala – 由SBT解决的本地依赖关系,但不是Play解决的!骨架
- Hadoop小文件解决方案-基于NameNode内存和MapReduce性能解决方案
- 【已解决】使用vue-electron脚手架进行vuex赋值时,失败的解决办法。
- Go 自定义日期时间格式解析解决方案 - 解决 `parsing time xx as xx` 错误
- 如何解决人智商不够?
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
JavaScript & jQuery
David Sawyer McFarland / O Reilly / 2011-10-28 / USD 39.99
You don't need programming experience to add interactive and visual effects to your web pages with JavaScript. This Missing Manual shows you how the jQuery library makes JavaScript programming fun, ea......一起来看看 《JavaScript & jQuery》 这本书的介绍吧!