TCP粘包半包问题
TCP粘包和半包的问题分析
TCP粘包原因:
1、发送方每次写入数据<套接字缓冲区大小;tcp相关算法整合碎片化数据包
2、接收方读取(接收)套接字缓冲区数据不够及时
半包原因:
1、发送方写入数据>套接字缓冲区大小
2、发送的最大报文长度大于MSS,网络包大于协议的MTU(最大传输单元,1500字节)必须拆包
TCP粘包半包根因分析:
TCP协议是面向连接的、可靠的、基于字节流的传输层通信协议,是一种流式协议,消息无边界会有粘包和拆包问题
TCP粘包和半包的解决方案
解决TCP粘包,半包问题的根本:找出消息的边界
方式 | 用法 | 寻找边界的方式 | 优势 | 弊端 | 推荐度 |
---|---|---|---|---|---|
封装成帧 | 固定长度 | 满足固定长度的数据就是一个完整消息 | 实现简单 | 长度不好定义,容易造成空间浪费 | 不推荐 |
封装成帧 | 分隔符 | 两个分隔符之间的消息就是完整的消息 | 实现简单,空间不浪费 | 消息内容本身也有分隔符时需要转义,且需要扫描消息内容性能不高 | 推荐 |
封装成帧 | 固定长度字段存消息长度 | 先解析固定长度字段获取消息内容的长度,再根据该长度读取具体的消息内容 | 精确定位消息数据,特殊内容也不需要转义 | 理论上长度有限制需要提前预知可能的最大长度从而定义消息内容占用的字节数 | 超级推荐 |
帧的组成为:Fixed length header + Variable length body
Netty解决粘包和半包问题
1,Netty提供了针对封装成帧这种形式下不同方式的编解码器,解码就是将网络中的一些原始数据解码成上层应用的数据;与解码对应的就是编码,上层应用在发送数据的时候要按照对应的方式将数据进行编码然后交给底层
2,数据进来要解码,数据出去要编码,Netty提供了开箱即用的编解码器
封装成帧的Netty编解码器:
用法 | 解码 | 编码 |
---|---|---|
固定长度(不推荐) | FixedLengthFrameDecoder | 不需要 |
分隔符(相对推荐) | DelimiterBasedFrameDecoder(特殊的换行符:LineBasedFrameDecoder | 应用层在每条消息后加上对应的分隔符即可 |
固定长度字段存消息长度 | LengthFieldBasedFrameDecoder | LengthFieldPrepender |
Pipeline中编解码器的排列: | ||
LengthFieldBasedFrameDecoder详解:
LengthFieldBasedFrameDecoder在构造时有4个重要参数,详解如下:
1,lengthFieldOffset:length域的偏移,正常情况下读取数据从偏移为0处开始读取,如果有需要可以从其他偏移量处开始读取
2,lengthFieldLength:length域占用的字节数
3,lengthAdjustment:在length域和content域中间是否需要填充其他字节数
4,initialBytesToStrip:解码后跳过的字节数