← 返回首页

TCP粘包/拆包问题如何解决?

核心原因:

TCP 是面向流(Stream-oriented)的协议,它没有“消息”的概念,只有字节流。发送方发送的两个数据包 ["Hello", "World"],在接收方看来可能变成:

  1. 粘包:["HelloWorld"] (两个包粘在一起)
  2. 拆包:["Hel", "loWor", "ld"] (一个包被拆成三次接收)
  3. 混合:["HelloW", "orldNextMsg..."]

长度字段 + 内容(Length-Prefix)—— 最推荐/通用

原理:在消息头中定义一个字段(通常是 4 字节整数),明确说明后续消息体的长度。

  • 格式:[4字节长度][N字节内容]例如:00 00 00 05 (长度5) + Hello
  • 处理方式:先读 4 字节,解析出长度 N。
    • 检查缓冲区剩余数据是否够 N 字节。
    • 如果够,截取 N 字节处理;如果不够,等待后续数据凑齐。
  • 优点:完美解决二进制数据包含任意字符的问题(无需转义)。
    • 效率高,只需读一次头部即可知道要读多少。
    • 业界标准做法(如 Netty, gRPC, Protobuf, Thrift 默认都采用此方式)。
  • 缺点:需要预先约定长度字段的编码格式(大端/小端)和占用字节数。
  • 适用场景:绝大多数自定义二进制协议、高性能 RPC 框架。