什么是拆包/粘包
TCP 粘包/拆包
半包:读取的数据不是一个数据包
粘包:读取的数据超过一个数据包
image.png
粘包问题的解决策略
业界的主流协议的解决方案
- 消息定长,报文大小固定长度,例如每个报文的长度固定为 200 字节,如果不够空位补空格;
- 包尾添加特殊分隔符,例如每条报文结束都添加回车换行符(例如 FTP 协议)或者指定特殊字符作为报文分隔符, 接收方通过特殊分隔符切分报文区分;
- 将消息分为消息头和消息体,消息头中包含表示信息的总长度(或者消息体长度)的字段;
- 更复杂的自定义应用层协议。
netty的解决方案
将 channel 中的数据读取时候经过解析, 如果不是一个完整的数据包, 则解析失败, 将这块数据包进行保存, 等下次解析时再和这个数据包进行组装解析, 直到解析到完整的数据包, 才会将数据包进行向下传递。
什么是编码和解码
编、解码技术
编码:序列化,用于网络传输,数据持久化。
解码:反序列化
Netty 为什么要提供编解码框架?
在保证定制扩展性的基础上,尽量降低用户的开发难度和开发量,提升开发效率。
Netty 中常用的解码器
Netty 默认提供了多个解码器,可以进行分包的操作,满足 99%的编码需求。
如何区分一个整包消息,通常有如下 4 种做法:
- 固定长度,例如每 120 个字节代表一个整包消息,不足的前面补位。解码器在处理这类定常消息的时候比较简单, 每次读到指定长度的字节后再进行解码;
- 通过回车换行符区分消息,例如 HTTP 协议。这类区分消息的方式多用于文本协议;
- 通过特定的分隔符区分整包消息;
- 通过在协议头/消息头中设置长度字段来标识整包消息。
ByteToMessageDecoder 抽象解码器
将字节数组编程对象,没有考虑到粘包的问题。
io.netty.handler.codec.ByteToMessageDecoder#channelRead
LineBasedFrameDecoder 行解码器
解码一行
DelimiterBasedFrameDecoder 分隔符解码器
是按照指定分隔符进行解码的解码器, 通过分隔符, 可以将二进制流拆 分成完整的数据包。
FixedLengthFrameDecoder 固定长度解码器
FixedLengthFrameDecoder 固定长度解码器,它能够按照指定的长度对消息进行自动解码,开发者不需要考虑 TCP 的 粘包/拆包等问题,非常实用。
LengthFieldBasedFrameDecoder 通用解码器
通过在协议头/消息头中设置长度字段来标识整包消息。
Netty 编码器原理和数据输出
writeAndFlush 事件传播
将数据写到发送缓存中,同时也能刷新到channel中
MessageToByteEncoder 抽象编码器
将对象编译成字节数组
自定义编、解码
MessageToMessageDecoder 抽象解码器
Netty 的二次解码器,它的职责是将一个对象二次解码为其它对象。
ObjectEncoder 序列化编码器
实现 Serializable 接口的对象序列化为 byte []
LengthFieldPrepender 通用编码器
长度字段通用编码器。








网友评论