网络 TCP协议

TCP 没有「消息」这个概念

新手写 socket 程序几乎都会撞上同一个困惑:发送端调了三次 send,接收端一次 recv 收到了全部;或者反过来,一次发送分两次才收齐。这就是俗称的"粘包/拆包"。

先纠正一个说法:这不是 TCP 的缺陷。TCP 是字节流协议,它只保证字节的顺序和可靠性,从设计上就不存在"消息边界"。你发的每条"消息",在 TCP 眼里只是字节序列的片段。发送端 Nagle 算法会攒小包,接收端缓冲区会按到达顺序吐字节——边界本来就不该存在。

整体链路示意
整体链路示意

所以解决方案只有一种思路:在应用层自己画边界。三种经典画法:

工程上还有两个放大器要注意:Nagle 算法会把小包合并(低延迟场景 TCP_NODELAY 关掉它),接收端缓冲区不够时一次只能吐出半条消息——所以读取循环必须能处理"数据还没到齐"的状态,按协议状态机读,而不是按 read 次数读。

把"字节流"这三个字真正吃透,粘包问题就从玄学变成了几何题。