← 返回首页
TCP粘包/拆包问题如何解决?
核心原因:
TCP 是面向流(Stream-oriented)的协议,它没有“消息”的概念,只有字节流。发送方发送的两个数据包 ["Hello", "World"],在接收方看来可能变成:
- 粘包:["HelloWorld"] (两个包粘在一起)
- 拆包:["Hel", "loWor", "ld"] (一个包被拆成三次接收)
- 混合:["HelloW", "orldNextMsg..."]
长度字段 + 内容(Length-Prefix)—— 最推荐/通用
原理:在消息头中定义一个字段(通常是 4 字节整数),明确说明后续消息体的长度。
- 格式:[4字节长度][N字节内容]例如:00 00 00 05 (长度5) + Hello
- 处理方式:先读 4 字节,解析出长度 N。
- 检查缓冲区剩余数据是否够 N 字节。
- 如果够,截取 N 字节处理;如果不够,等待后续数据凑齐。
- 优点:完美解决二进制数据包含任意字符的问题(无需转义)。
- 效率高,只需读一次头部即可知道要读多少。
- 业界标准做法(如 Netty, gRPC, Protobuf, Thrift 默认都采用此方式)。
- 缺点:需要预先约定长度字段的编码格式(大端/小端)和占用字节数。
- 适用场景:绝大多数自定义二进制协议、高性能 RPC 框架。