1.黏包
1.为什么出现黏包
1.发送方原因
tcp默认会使用Nagle算法,而Nagle算法主要做两件事。1)只有上一个分组得到确认,才会发送下一个分组 2)收集多个小分组,在一个确认到来时一起发送。
2.接收方原因
tcp接收到分组时,并不会立刻送至应用层处理,或者说应用层并不一定会立即处理;实际上,tcp将收到的分组保存至接收缓存里,然后应用程序主动从缓存里读收到的分组。这样一来tcp接收分组的速度大于应用程序读分组的速度,多个包就会被存在缓存,应用程序读的时候,就会读到多个首尾相接黏到一起的包。、
简单来说,在流传输中出现,udp是不会出现的,因为udp是面向数据报的,有消息边界。
1发送端需要等缓冲区满才发送出去,造成粘包
2接收方不及时接收缓冲区的包,造成多个包接收
具体点:
(1)发送方引起的粘包是由TCP协议本身造成的,TCP为提高传输效率,发送方往往要收集到足够多的数据后才发送一包数据。若连续几次发送的数据都很少,通常TCP会根据优化算法把这些数据合成一包后一次发送出去,这样接收方就收到了粘包数据。
(2)接收方引起的粘包是由于接收方用户进程不及时接收数据,从而导致粘包现象。这是因为接收方先把收到的数据放在系统接收缓冲区,用户进程从该缓冲区取数据,若下一包数据到达时前一包数据尚未被用户进程取走,则下一包数据放到系统接收缓冲区时就接到前一包数据之后,而用户进程根据预先设定的缓冲区大小从系统接收缓冲区取数据,这样就一次取到了多包数据。
粘包情况有两种,一种是粘在一起的包都是完整的数据包,另一种情况是粘在一起的包有不完整的包。
在处理定长结构数据的粘包问题时,分包算法比较简单;在处理不定长结构数据的粘包问题时,分包算法就比较复杂。特别是粘在一起的包有不完整的包的粘包情况,由于一包数据内容被分在了两个连续的接收包中,处理起来难度较大。实际工程应用中应尽量避免出现粘包现象。
-
什么时候需要处理黏包现象
不是所有的粘包现象都需要处理,若传输的数据为不带结构的连续流数据(如文件传输),则不必把粘连的包分开(简称分包)。但在实际工程应用中,传输的数据一般为带结构的数据,这时就需要做分包处理。
(1)如果发送方发送的多个分组本来就是同一个数据的不同部分,比如一个很大的文件被分成多个分组发送,这时,当然不需要处理粘包的现象;
(2)但如果多个分组本毫不相干,甚至是并列的关系,我们就一定要处理粘包问题了。比如,我当时要接收的每个分组都是一个有固定格式的商品信息,如果不处理粘包问题,每个读进来的分组我只会处理最前边的那个商品,后边的就会被丢弃。这显然不是我要的结果。
-
如何处理黏包问题
(1).对于发送方造成的黏包现象,我们可以通过关闭Nagle算法来解决问题,但是降低了网络发送效率,影响应用程序性能。
(2).通过优化程序设计、精简接收进程工作量、提高接收进程优先级等措施,使得其及时接收数据,从而尽量避免出现黏包现象。
(3).进行封包与拆包
2.封包与拆包
-
封包
封包就是给一段数据加上包头,这样一来数据包就分为包头和包体两部分内容了(以后讲过滤非法包时封包会加入"包尾"内容)。包头其实上是个大小固定的结构体,其中有个结构体成员变量表示包体的长度,这是个很重要的变量,其他的结构体成员可根据需要自己定义。根据包头长度固定以及包头中含有包体长度的变量就能正确的拆分出一个完整的数据包。
-
拆包
(1)动态缓冲区暂存方式。之所以说缓冲区是动态的是因为当需要缓冲的数据长度超出缓冲区的长度时会增大缓冲区长度。
(2)利用底层的缓冲区来进行拆包