1、什么是粘包和半包?
粘包:一次接收全部消息
半包:分多次接收到多个不完整的消息
2、为什么TCP应用会出现粘包和半包现象
粘包的主要原因:
- 发送方每次写入数据 < 套接字缓冲区大小
- 接收方读取套接字缓冲区数据不及时
半包的主要原因:
- 发送方写入数据 > 套接字缓冲区大小
- 发送的数据大于协议的MTU(Maximum Transmission Unit,最大传输单元),必须拆包
收发:
一个发送可能被多次接收,多个发送可能被一次接收
传输:
一个发送可能占用多个传输包,多个发送可能公用一个传输包
根本原因:TCP是流式协议,消息无边界
3、解决粘包和半包问题的几种常用方法
解决问题的根本手段:找出消息边界:
方式\比较 | 寻找消息边界方式 | 优点 | 缺点 | 推荐度 |
---|---|---|---|---|
TCP连接改成短链接,一个请求一个短连接 | 建立连接到释放连接之间的信息即为传输消息 | 简单 | 效率低下 | 推荐度 |
(封装成帧)固定长度 | 满足固定长度即可 | 简单 | 空间浪费 | 不推荐 |
(封装成帧)分隔符 | 分隔符之间 | 空间不浪费,也比较简单 | 内容本身出现分隔符时需转义,所以需要扫描内容 | 推荐 |
(封装成帧)固定长度字段存内容的长度信息 | 先解析固定长度的字段获取长度,然后读取后续内容 | 精确定位用户数据,内容也不用转义 | 长度理论上有限制,需提前预知可能的最大长度从而定义长度占用字节数 | 推荐 |
(封装成帧)其他方式 | json | 需要衡量实际场景,对现有协议的支持 |
4、Netty对三种常用封帧方式的支持
方式\支持 | 解码 | 编码 |
---|---|---|
固定长度 | FixedLengthFrameDecoder | 简单 |
分隔符 | DelimiterBasedFrameDecoder | 简单 |
固定长度字段存个内容的长度信息 | LengthFieldBasedFrameDecoder | LengthFieldPrepender |
5、解读Netty处理粘包、半包的源码
解码的核心工作流程
解码中两种数据积累器的区别
三种解码器的额外控制参数有哪些