首页 > 编程知识 正文

tcp粘包的原因,解决tcp粘包问题

时间:2023-05-06 17:36:30 阅读:16086 作者:2052

TCP分组现象是套接字网络编程中的端到端通信,由客户端端口、服务端口、客户端IP服务端IP传输协议组成的五组可以清楚地识别一个连接。 在TCP套接字编程中,发送端和接收端都有一对套接字。 发送侧为了更有效地将发往多个接收侧的分组发送到接收侧,采用优化算法(Nagle算法),将多次间隔小、数据量小的数据汇总成一个数据量大的数据块这样,接收方必须使用高效科学的拆包机制识别这些数据。 什么是TCP包问题?

粘包、打开包的表现,现在假设客户端向服务端连续发送了两个数据包,用packet1和packet2来表现,服务端接收的数据可以分为以下三类。

第一种情况是接收方正常接收到两个数据包,即没有发生拆包和粘着现象,这种情况不在本文的讨论范围内。

第二种情况下,接收端只接收一个分组,在TCP中不发生分组丢失,所以该一个分组包含发送端发送的两个分组的信息,该现象是分组的粘合。 这种情况对于接收端来说很难处理,因为接收端不知道这两个分组的边界。

第三种情况有两种表现形式,如下图所示。 接收方接收到了两个数据包,但这两个数据包要么不完整,要么多余出来了一个,发生了拆包和粘接。 在这两种情况下,如果不施加特别的处理,对于接收端来说也同样难以处理。

什么是TCP包问题? TCP数据包是发送端发送的几个数据包数据到达接收端时粘在一个数据包上的东西。 从接收缓冲区来看,下一个包数据的开头跟在前一个包数据的末尾。 数据包粘在一起的原因有很多种,有可能来自发送端,也有可能来自接收端。

TCP数据包的原因1 )发送端的原因

缺省情况下,TCP使用Nagle算法。 主要作用是减少网络中消息段的数量。 另一方面,Nagle算法主要做两件事。

如果仅在确认了上一个数据包的情况下发送下一个数据包以收集多个小数据包,并在一个确认到来时一起发送Nagle算法,则发送端可能会出现数据包粘滞问题

(2)接受方原因

TCP在接收到分组时,并不是立即传递给APP应用层来处理,或者不是APP应用层立即处理。 实际上,TCP将接收的分组存储在接收缓存中,并且APP应用主动地从缓存读取接收的分组。 因此,如果TCP将包接收到缓存中的速度快于APP应用程序从缓存中读取包的速度,则多个包可能会被缓存,并且APP应用程序可能会读取成功粘在一起的多个包。 什么时候需要处理粘合包现象?

另一种说法是,如果要发送的数据大于TCP发送缓冲器的空闲容量,则发生分组丢失。

2、发送的数据大于MSS (最大消息长度),TCP在发送前开箱。

3、如果要发送的数据小于TCP发送缓冲器的大小,并且TCP一次发送已经被多次写入缓冲器的数据,则生成阻塞分组。

4、接收数据侧的APP应用层不能及时读取接收缓冲器内的数据,发生数据包的粘贴。

什么时候需要处理粘合包现象? 如果发送侧发送的多组数据原本是相同块数据的不同部分,例如一个文件被分成多个部分来发送,则该多个分组无关或并行关系,则必然处理分组现象如何处理数据包现象? (1)发送侧

发送方粘贴数据包的问题可以通过关闭Nagle算法来解决。 可以使用TCP_NODELAY选项关闭算法。

)2)接收方

接收方无法处理数据包的粘贴现象,只能将问题交给APP应用层处理。

)2) APP应用层

解决APP应用层的方法简单易行,不仅可以解决接收端的粘合包装问题,还可以解决发送端的粘合包装问题。

解决方案:循环处理。 当APP应用程序从接收缓存读取包时,在读取完一个数据后,应该循环读取下一个数据直到处理完所有数据,那么如何确定每个数据的长度呢?

数据格式:各数据有固定格式(起始符、结束符),该方法很简单,但在选择起始符和结束符时,请务必确保各数据内部不包含起始符和结束符。

发送信长:发送各数据时,将数据的长度汇总发送。 例如,规定数据的前4位是数据的长度,而APP应用层在处理时可以根据长度来确定每个包的开始位置和结束位置。

另一种分隔符方法是封装要发送的数据包时,使用固定符号作为终结符。 这样,在接收到数据后,如果显示了结束符,即人为地分离数据包,而一个数据包上没有显示结束符,则判断为发生了分包,可以等待下一个数据包被显示后汇总为完整的数据包。 此方法适用于文本传输的数据,例如/

另一种方法是向数据包添加长度。 这是一种将数据包的长度信息(或可以计算数据包总长度的信息)封装在数据包中的固定位置,服务器接收到数据后,首先分析数据包长度,然后根据数据包长度截取数据包的方法。 这种方法在定制协议中很常见。 但是,一个小问题是客户端的第一个分组长度封装有错误。 那么,以后接收到的所有数据包都可能发生分析错误。 (因为TCP建立连接后进行流式传输的机制。)。 要解决此问题,客户端必须关闭连接,然后重新打开。 我在处理这个问题时检查数据长度,及时人工处置接收到的有问题的数据包) )客户端有自动重传机制,所以不会在APP应用层导致数据不一致性)。

另一种说法是,通过以上分析,粘合包和拆包变得明确了。

发生的原因,那么如何解决这个问题呢?解决问题的关键在于如何给每个数据包添加边界信息,常用的方法有如下几个:

1、发送端给每个数据包添加包首部,首部中应该至少包含数据包的长度,这样接收端在接收到数据后,通过读取包首部的长度字段,便知道每一个数据包的实际长度了。

2、发送端将每个数据包封装为固定长度(不够的可以通过补0填充),这样接收端每次从接收缓冲区中读取固定长度的数据就自然而然的把每个数据包拆分开来。

3、可以在数据包之间设置边界,如添加特殊符号,这样,接收端通过这个边界就可以将不同的数据包拆分开。

UDP会不会产生粘包问题呢?

TCP为了保证可靠传输并减少额外的开销(每次发包都要验证),采用了基于流的传输,基于流的传输不认为消息是一条一条的,是无保护消息边界的(保护消息边界:指传输协议把数据当做一条独立的消息在网上传输,接收端一次只能接受一条独立的消息)。

UDP则是面向消息传输的,是有保护消息边界的,接收方一次只接受一条独立的信息,所以不存在粘包问题。

举个例子:有三个数据包,大小分别为2k、4k、6k,如果采用UDP发送的话,不管接受方的接收缓存有多大,我们必须要进行至少三次以上的发送才能把数据包发送完,但是使用TCP协议发送的话,我们只需要接受方的接收缓存有12k的大小,就可以一次把这3个数据包全部发送完毕。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。