UDP“粘包”

什么叫“粘包”?

“粘包”指的是,分次发送的数据包,接收端接收一次数据,读到了对应发送端多于一次的数据。例如,发送端先发送了一个数据包

AAAA

后续又发送了一个数据包

BBBB

接收端在读取数据时,读取一次,收到的数据是

AAAABBBB

这就是某些情况下所说的粘包。

UDP通信会不会粘包?

对于UDP通信,理论上(未究其根源,根据搜索到的相关说法)不会发生粘包,因为UDP数据包各有自己的“边界”(同样的原因,姑且认为此说法成立)。

工程中遇到的UDP“粘包”

实践中,使用UDP通信过程中,还是遇到了“粘包”现象。就笔者所遇到的情况就是,代码中相邻两条指令,各发送一个UDP数据包,接收端得知有数据到达,读取一次,得到了发送端两次发送内容的拼合结果。

UDP“粘包”原因分析

就实践中遇到的UDP“粘包”问题,场景有二,一是Windows平台,接连发送两个UDP包;二是基于单片机的平台,利用串口发送数据到串口-网络转换模块,发送不同数据包间隔时间比较短的时候。

对于场景一,做了测试,在两条指令之间加延时,并不总是有效。可能跟系统底层网络传输实现细节或者应用程序与底层的衔接有关。

对于场景二,与串口-网络转换模块实现有关,(似乎)其实现中是定时将从串口获取的数据串以UDP数据包发送出去。如果两个数据包未被其识别为两个数据包(视实现的不同,也可能仅仅是定时将缓存的串口数据封包为UDP数据包发送出去而已),则作为一个更长的包发送出去(此种情况,串口数据包长度、串口波特率、串口-网络转换模块内部实现在某些组合下,还会发生“拆包”现象,此处不展开)。

UDP“粘包”的影响

UDP通信过程中,不论有意设计还是无意实现,都相当与存在一个事实上的“协议”。如果在发送和接收时,意识不到UDP“粘包”的可能,无意之中会基于“一发一收、不粘不拆”的前提。此时,在发生粘包时,如果是数据包定长且只做长度校验,则粘连的数据包会被认为是无效的数据包而丢弃,即参与粘连的数据包都成了无效包;如果只根据魔术字(magic number)之类的手段识别包头,则粘连的数据包只有位于开头位置的数据会被识别,后续的参与粘连的数据包都被丢弃了,形成事实上的无效包。无效包是否会影响系统的运作,影响程度如何,视系统敏感程度而异,不展开。

UDP“粘包”的克服

从发送端而言,对于场景一,如果加延时不保证总是有效,可以引入发送队列,另设定时或轮询机制,从队列中依次取数据、发数据。

从发送端而言,对于场景二,调整串口数据包长度、串口波特率等串口-网络转换模块参数,降低“粘包”(及“拆包”)发生的概率。

对于接收端而言,要正视事实上会发生“粘包”(及“拆包”)的现实,引入FIFO队列、环形缓冲等,依靠数据串内的逻辑边界而不是依赖接收数据包的天然边界来分割数据包。必要时辅以有助于上述手段实现的协议设计。

题后

从工程的角度,重在解决问题,其次才是辩论是非(此过程不排斥对底层实现的深层探索)。处理资源更丰富、程序实现更灵活、应变能力更强的一方,在不违背大原则的前提下(如技术要求等),最好多做些工作,来实现提高整体通信可靠性的目标。如果过多的按照条条杠杠“苛责”处理资源紧张、程序实现灵活度受限、应变能力偏弱的一方,最终结果可能就是整体通信可靠性既未达到本来可以达到的程度,也在陪弱势一方调试、测试、辩论过程中浪费掉很多的时间,牵扯到很多的精力,而这些时间精力如果用于强势的一方调整自己的实现去达到同样的目标,可能重复十次八次还有富余。

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
UDP(User Datagram Protocol)是一种无连接的、不可靠的传输协议,它提供了一种面向消息的传输方式。在UDP中,数据被分割成一个个的数据包(也称为数据报),然后通过网络传输。由于UDP不提供可靠性保证和流控制机制,因此在使用UDP进行通信时,可能会出现粘包的问题。 粘包是指发送方连续发送的数据包被接收方合并成一个大的数据包或者多个数据包被接收方合并成一个大的数据包的现象。这种现象通常发生在发送方连续发送数据包时,由于网络传输的不确定性,接收方可能无法准确地将每个数据包分开接收。 在UDP协议中,由于没有可靠性保证和流控制机制,发送方发送的数据包可能会因为网络延迟、丢包等原因被接收方延迟接收或者接收不到,造成接收方在一次接收时接收到多个数据包。另外,UDP协议中没有消息边界的概念,接收方无法准确地知道每个数据包的边界,导致多个数据包被合并成一个大的数据包。 解决UDP协议中的粘包问题可以采用以下方法: 1. 使用固定长度的数据包:发送方在发送数据包时,将每个数据包的长度固定为一个固定值,接收方根据固定长度来解析每个数据包。 2. 使用分隔符:发送方在发送数据包时,在每个数据包的末尾添加一个特定的分隔符,接收方根据分隔符来解析每个数据包。 3. 使用消息头:发送方在发送数据包时,在每个数据包的开头添加一个消息头,消息头中包含了数据包的长度信息,接收方根据消息头中的长度信息来解析每个数据包。 4. 使用应用层协议:在UDP协议的基础上,使用应用层协议进行数据的封装和解析,应用层协议可以提供更加可靠的数据传输机制,避免粘包问题的发生。 以上是一些常见的解决UDP协议粘包问题的方法,具体使用哪种方法取决于具体的需求和应用场景。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值