TCP 半包粘包问题

什么是粘包现象

TCP 粘包是指发送方发送的若干包数据到接收方接收时粘成一包,从接收缓冲区看,后一包数据的头紧接着前一包数据的尾

为什么出现粘包现象

(1)发送方原因
TCP 默认会使用 Nagle 算法。而 Nagle 算法就是仅在下列任一条件下才能发送数据。如果两个条件都不满足,那么暂时等待一段实际后再进行数据发送

  • 已发送的数据都已经收到确认应答时
  • 可以发送最大段长度(MSS)的数据时

所以,正是 Nagle 算法造成了发送方有可能造成粘包现象

(2)接收方原因
TCP 接收到分组时,并不会立刻送至应用层处理,或者说,应用层并不一定会立即处理;实际上,TCP 将收到的分组保存至接收缓存里,然后应用程序主动从缓存里读收到的分组。这样一来,如果 TCP 接收分组的速度大于应用程序读分组的速度,多个包就会被存至缓存,应用程序读时,就会读到多个首尾相接粘到一起的包

什么时候需要处理粘包现象

如果发送方发送的多个分组本来就是同一个数据的不同部分,比如一个很大的文件被分成多个分组发送,这时,当然不需要处理粘包的现象

但如果多个分组本毫不相干,甚至是并列的关系,就一定要处理粘包问题了。比如,要接收的每个分组都是一个有固定格式的商品信息,如果不处理粘包问题,每个读进来的分组只会处理最前边的那个商品,后边的就会被丢弃

如何处理粘包现象

  • 发送方
    对于发送方造成的粘包现象,我们可以通过关闭 Nagle 算法来解决,使用 TCP_NODELAY 选项来关闭 Nagle 算法

  • 接收方
    TCP 并没有处理接收方粘包现象的机制,只能在应用层进行处理

应用层的处理简单易行!不仅可以解决接收方造成的粘包问题,还能解决发送方造成的粘包问题

基本思路就是不断从 TCP 缓冲区中读取数据,每次读完都需要判断是否是一个完整的数据包:

  • 若当前读取的数据不足以拼接成一个完整的包,就保留该数据,继续读,直到得到一个完整的包
  • 若当前读到的数据加上已读取的数据足够拼成一个数据包,那就将已经读取得数据拼接上本次读取得数据,够成一个完整的业务数据包传递到业务逻辑,多余的数据仍保留,以便和下次读到的数据尝试拼接

两种途径:

  • 格式化数据:每条数据有固定的格式(开始符、结束符),这种方法简单易行,但选择开始符和结束符的时候一定要注意每条数据的内部一定不能出现开始符或结束符

  • 发送长度:发送每条数据的时候,将数据的长度一并发送,比如可以选择每条数据的前 4 位是数据的长度,应用层处理时可以根据长度来判断每条数据的开始和结束

你可能感兴趣的:(TCP 半包粘包问题)