如何解决TCP粘包问题?

  • 当TCP两端建立连接后,第一次发送100个字节,第二次再发送100个字节
  • 接收端不一定会分两次接收到100字节,为了提高效率,发送端经常将多个数据包缓存起来,合成一个数据包进行发送

如何解决TCP粘包问题?

 

第一个包是给应用程序A使用的,第二包是给应用程序B使用的,而在接收端可能会错误地以为这两个包都是给应用程序A使用的

TCP粘包问题

简单来说,就是两个不同的数据包,被合并成一个包,造成错误处理

TCP默认使用Nagle算法,主要作用是减少网络中报文段的数量,发送端会将较小的内容拼接成大的内容,一次性发送到服务器端

TCP接收数据包时,并不会马上交到应用层进行处理,或者说应用层并不会立即处理。实际上接收到的数据报会保存在缓存里,然后应用程序主动从缓存读取收到分组

当传输文件这种数据时,流式的传输非常适合,但传输指令类的数据结构时,流式模型就有一个问题:无法知道指令的结束。

解决TCP粘包问题的方法

核心思想:如果多个数据包合并在一块,内部应该如何分割

短连接

  • 需要发送数据的时候建立TCP连接,发送完一个数据包后就断开TCP连接,这样接收端自然就知道数据结束
  • 多次建立TCP连接,性能低下

长连接

  • 接受端如果知道如何对数据包进行分割,便可以解决粘包问题
  • 发送端可以在发送数据之前,向接收端告知发送内容的大小
  • 所以对于处理粘包的关键在于提前获取到数据包的长度,无论这个长度是提前商定好的还是写在数据包的开头

长连接-第一种做法

  • 选一个固定的字符作为数据包的结束标志,发现这个字符就代表一个数据包传输完成
  • 但是这一些情况下,很难确定,字符到底是结束标志,还是属于原本要传输的数据内容
  • 实现比较复杂、低效

长连接-第二种做法

  1. 在每次发送数据的固定偏移位置,写入数据包的长度
  2. 接收端只要一开始读取固定偏移的数据,可以知道这个数据包的长度
  3. 当收到的数据长度不足时,就继续接收直到满足长度
  4. 当收到的数据多于固定长度时,需要截断数据,并将多余的数据缓存起来,视为长度不足需要再次接收处理。