68d93301bcb3cb71b89c75c23cd6e32b
浅析 TCP 粘包与拆包问题

我们知道,TCP是面向字节流的协议,是没有“包”的概念,因此,严格意义来说。“粘包”和“拆包”的说法不太严谨,但是有助于形象地理解这两种现象。本文将比较简单地分析“粘包”与“拆包”这两种概念,并阐述一下常见的解决办法,希望能让大家对这两个问题有个大致的了解。

目录

  1. 什么是粘包?
  2. 什么是拆包?
  3. 出现原因
  4. 解决办法

1. 什么是粘包?

“粘包”是指TCP发送方的若干个“数据包”到接收方被粘在一起。从接收缓冲区看,后一包数据的头紧接着前一包数据的尾。这些数据包可能是一个很大的消息拆分的小包,也有可能本身就是很小的完整包。
这主要是因为TCP是面向字节流的,是没有消息边界的。所以,UDP是没有这个问题的。
粘包情况有两种,一种是粘在一起的包都是完整的数据包,另一种情况是粘在一起的包有不完整的包。

粘包 图片来自网络

粘包 图片来自网络

上图中从上到下的四种场景,只有第一个没有粘包,第二个是完整的粘包,最后两个是不完整的粘包。

当然,不是所有情况都要考虑粘包,有两种场景不需要考虑:

  1. TCP使用短链接,不需要考虑粘包问题。
    因为只要发送方主动关闭连接,就表示一条消息发送完毕,接收方 read() 返回0,从而得知消息结尾。
  2. 发送非结构化数据时,如文件传输,这样发送方只管发送,接收方只管接收存储就 ok,不用考虑粘包;

2. 什么是拆包?

“拆包”是与“粘包”相对的,是指出现上述的“粘包”现象后,接收方要从没有边界的数据包中拆分出各个完整的数据包。
一般有两种“拆包”的方法:
1. 动态缓冲区暂存方式

1) 为每一个连接动态分配一个缓冲区,同时把此缓冲区和SOCKET关联,常用的是通过结构体关联。
2)当接收到数据时首先把此段数据存放在缓冲区中。
3)判断缓存区中的数据长度是否够一个包头的长度,如不够,则不进行拆包操作。

top Created with Sketch.