|
最近在做设计评审时,下面工程师在对用UDP和TCP中展开了激烈的讨论,而一个同事发表了这样的观点:"能用TCP绝不用UDP,UDP实在是太不靠谱了~"说实在的我也很理解,但是对于这样的言论也容易误导人,导致很多初学者在尝试使用UDP设计的时候,只要出现一些埋得比较深的问题就会一棍子把UDP给拍死,这是我觉得不应该的。其实UDP并没有那么不靠谱。1
UDP数据包
首先我们看看UDP的数据包格式,数据内容本身的正确性是由UDP的**校验和(Checksum)**机制保证的:如果数据包在传输中发生比特错误(如电磁干扰),接收端会直接丢弃该包,不会将错误数据传递给应用层。然而UDP的“不可靠”主要是如下三点:不保证数据包到达(可能丢包)不保证顺序性(可能乱序)不主动控制发送速率(可能拥塞丢包)[/ol]所以有些数据错乱问题的过,真不该让UDP来背,往往有时候就是自己设计的应用层逻辑设计不当。
比如下面常见的一些场景:
场景1:乱序未处理? 问题:接收端先收到后发送的包(如视频流的第2帧早于第1帧到达)。
? 根因:应用层未实现乱序重组逻辑,直接按接收顺序处理数据。
? 改进:在数据包头部添加序列号(Sequence Number),由应用层缓存并排序。
场景2:分包/合包逻辑缺失? 问题:发送端传输了超过MTU的大数据包,IP层自动分片,但接收端未正确处理。
? 根因:应用层未实现手动分包/合包逻辑,依赖IP分片(可靠性差)。
? 改进:在应用层主动将大数据拆分为≤1472字节的块,并为每个块添加序号和偏移量。
场景3:未区分丢包与延迟? 问题:误将延迟较高的包视为丢失,导致逻辑错误。
? 根因:未设置合理的超时重传机制。
? 改进:为关键数据添加ACK确认与重传,非关键数据允许丢弃(如实时音视频)。
2
丢包原因
其实UDP的丢包主要还是与网络环境有关,
网络拥塞:路由器缓冲区溢出时,UDP包被优先丢弃(TCP会主动降速,UDP不会)。链路质量差:无线网络(如Wi-Fi、4G)易受干扰,物理层丢包率上升。IP分片丢失:若数据包超过MTU被分片,任一碎片丢失会导致整个UDP包不可用。虽然会丢包,但丢包 ≠ 数据错乱, 丢包只会导致部分数据缺失(如视频卡顿、语音中断),不会破坏已接收数据的正确性,数据内容错误,已被UDP校验和过滤。
3
可靠的UDP协议设计
从前面UDP的结构大家就知道,其实它挺简洁的,UDP既然不解决这些问题,那就应用层去弥补,说实在有更多的灵活度。UDP应用层需解决乱序、完整性、丢包三个问题就本上就比较靠谱了。比如传输协议中增加一些字段:| 序列号 (4B) | 时间戳 (4B) | 载荷长度 (2B) | 载荷数据 (N B) |
为了处理乱序、重复、丢包检测等问题。
对于一些关键数据添加ACK确认与重传,一些实时数据丢包了也没关系,就不需要应答了~
最好是避免IP分片,控制数据包大小≤1472字节(假设MTU=1500),大数据传输时,主动在应用层分包并添加序号。
如果你加快异常时的收发效率,可以采用前向纠错(FEC),通过发送冗余数据包,允许接收端通过算法恢复部分丢失数据(如RTP协议中的FEC机制)。 |
|