TCP粘包问题是什么?你会如何去解决它?
前言:
TCP协议是面向字节流的,TCP没有消息边界保护的功能,所以TCP就会发生粘包和拆包的问题。
这一点不像UDP,因为UDP面向报文,所以它不会对报文进行处理,而是直接将报文作为一个整体,添加UDP头部
粘包和拆包是什么?
- 粘包:我举一个比较典型的例子:假如发送方发送了2个TCP报文段,但是接收方仅仅接收到了1个TCP报文段,这导致接收端应用程序无法区分两个TCP报文段的边界,也就无法进行数据处理
- 拆包:还是举一个例子:假如发送方发送了2个TCP报文段,接收方也接收到了2个报文段,但是收到的第一个TCP报文段中粘上了发送方发送的第2个报文段的一部分,这其实就是对第2个TCP报文段的拆包,同样接收方应用程序也无法处理和区分
发生粘包和拆包的原因是什么?
- 应用程序写入的数据大于套接字缓冲区大小,这将发生拆包问题
- 应用程序写入的数据小于套接字缓冲区大小,协议栈将多次写入的数据一并发出,这将产生粘包问题
- TCP分段,要发送的数据大于MSS,一个TCP报文装不下,所以进行分段,这将导致拆包问题
- 发送速率和接收速率不匹配,接收速度太慢,导致接收到的数据在缓冲区堆积,这将导致粘包问题
注意1: 应用层的数据先传递到发送方的发送缓冲区,等到发送缓冲区满了之后,再将数据封装成TCP包发送
- 如果缓冲区数据长度大于TCP双方商定的MSS,就会发生TCP分包
注意2: 粘包、拆包对象是数据本身,也即要发送的数据本身连在一块或者被分开了
粘包和拆包问题的解决方法
- 消息定长,通过固定每次发送的数据长度,然后接收方同样就以这个长度作为分界来区分前后两个不同的包
- 加包头,为每一个要数据添加一个
2字节或4字节 的长度标识,接收方程序每次先读取该长度,然后再读取相应数目的数据 - 尾部添加标记序列,比如
'\n' '\t' 等
|