在使用RTP协议时,如果需要网络对抗,保障QoS(Quality of Service,服务质量),我们需要通过序列号以及时间戳的比较,进行丢包判断。但是有个问题,比如一个RTP包,序列号为number1:5000,另一个RTP包序列号为number2:60000,可以说60000一定比5000大,是个更新的RTP包吗? 当然不是了,首先我们先重温下RTP数据包的结构。 在RFC3550中RTP固定报头结构按如下定义: [crayon-69c24079d5d94442276108/] 可以看到,RTP序列号sequence number用两字节表示,时间戳timestamp用四字节表示。所以序列号以及时间戳就存在一个取值范围。由于是无符号数,所以序列号范围为:[0,2^16-1],时间戳范围为:[0,2^32-1]。当达到最大值时,将发生所谓的回绕。例如,序列号到了2^16-1,下个包序列号就将是0。所以我们不能直接根据数学意义上的大小进行序列号以及时间戳的比较。 在WebRTC中定义了一个大小比较算法,包含数字回绕处理,判断是否是更新的数字。下面说下算法原理: 1)假设有两个U类型的无符号整数:value, prev_value; 2)定义一个常量kBreakpoint,为U类型取值范围的一半; 3)value > prev_value,满足value - prev_value = kBreakpoint时,value大于prev_value; 4)value与prev_value不相等,满足(U)(valude - prev_value) < kBreakpoint时,value大于prev_value。 总结起来就是value与prev_value距离小于取值范围的一半且不相等或者value与prev_value距离等于取值范围的一半,value大于prev_value,就可以说明value大于prev_value。 在modules\include\module_common_types_public.h,相应代码如下: [crayon-69c24079d5d9b651409254/] 顺便也说下如上函数的一个应用。在WebRTC丢包重传判断中(jitter_buffer模块),需要保存上一次收到的最新RTP序列号latest_received_sequence_number_,以便用于丢包判断(请参考:WebRTC研究:丢包判断),这个RTP包必须是新的数据,不能是重传的旧数据。所以每来一个RTP包时,可以将该RTP包序列号传入如上函数,与之前收到的最新RTP序列号进行对比,从而判断当前RTP包是不是最新的。相应代码如下: [crayon-69c24079d5d9d781878109/] 参考 [1].rfc1982.https://tools.ietf.org/html/rfc1982