什么是粘包和拆包?
-
粘包:指多条应用层消息在接收方一次性读到,数据"粘"在一起,无法区分消息边界。
- 例子:客户端连续发送
[Hello]
和[World]
,接收方一次recv()
得到[HelloWorld]
。
- 例子:客户端连续发送
-
拆包 :指一条应用层消息被 TCP 拆成多段传输,接收方需要多次
recv()
才能拼凑完整。- 例子:客户端发送
[HelloWorld]
,接收方第一次recv()
得到[Hello]
,第二次得到[World]
。
- 例子:客户端发送
一、为什么会出现粘包和拆包?
TCP 是面向字节流的协议,它只保证数据有序、不丢、不重复,但不会保留应用层消息的边界。
因此:
-
应用层发送的多条消息,可能被 TCP 合并在一起(粘包)。
-
一条消息可能被拆成多个数据包传输(拆包)。
二、粘包与拆包的场景
1. 粘包现象
客户端连续发送两条消息:
[Hello]
[World]
服务端可能一次 recv()
收到:
[HelloWorld]
👉 多条消息粘在一起。
2. 拆包现象
客户端发送一条很大的消息:
[HelloWorldHelloWorld... 很长的数据]
服务端可能第一次收到:
[HelloW]
第二次收到:
[orldHello...]
👉 一条消息被拆开。
三、产生原因
-
TCP 无消息边界:只是一条连续的字节流。
-
Nagle 算法:小包会合并传输。
-
接收端读取不及时:缓冲区积累数据,导致粘在一起。
-
消息过大:超过 MTU 或 TCP 缓冲区,只能拆分。
四、解决方案
1. 定长消息
-
每条消息固定大小,例如 1024 字节,不够补齐。
-
缺点:浪费空间。
2. 分隔符
-
在消息末尾加特殊字符(如
\n
、\r\n
)。 -
类似 HTTP 协议用
\r\n\r\n
分隔头和体。