WebRTC丢包重传简介

目录

概述

NACK

问题一、数据包真丢了,会一直重传吗?

问题二、重传次数不到最大限制次数,就会一直等待吗?

问题三、当大量丢包时,会全部重传吗?

NACK改进

总结

概述

WebRTC之所以可以优秀的完成音视频通讯,和它本身的丢包重传机制是密不可分的,今天我们就来看看其中的奥秘。

本文以M76版本展开,如果你的工程是基于其他版本开发的,也可以参考。

NACK

说到丢包重传就不得不提到NACK技术,那么NACK是什么呢。它的全称是Negative Acknowledgment Packet,意思是否定确认包,说到这里我们应该可以联想到ACK(Acknowledgment Packet,确认包)。没错,二者的意思是相反的。ACK表示通知对方我收到了你发给我的数据包,NACK表示通知对方我没有收到你发给我的数据包。

那么问题来了,为什么会导致对方明明发送了响应的数据包,而我没有收到呢?其中的原因有很多,比如网络问题,因为中间路由器转发丢失,延时较大导致被NACK(可能数据包还在传输中,只是到达时间比较久)等。

基于上述原因,NACK的存在是非常有必要的。它能够及时的通知发送端重传相应的数据包,保证接收端音频和视频的正常播放。NACK其实是RTCP包的一种,用来是对 RTP 数据传输层进行反馈,它包类型是 205。

问题一、数据包真丢了,会一直重传吗?

答案是否定的。会有哪些决定因素呢?首先看最大重传次数,源码中默认是10次。意思是如果相同seq_num的数据包被重传了10次,接收端依然没收到,就不再继续请求重传了。

const int kMaxNackRetries = 10;

处理方式是将该数据包从重传列表中移除,具体看源码:

基于问题一,于是我们引入了问题二。

问题二、重传次数不到最大限制次数,就会一直等待吗?

很不幸,答案是肯定的。NACK技术作为WebRTC对抗弱网的核心技术之一,有两种发送模式,一种是基于包序列号的发送,一种是基于时间序列的发送。 对于一个包因为不连续而被判为丢失后,接收端会主动请求重传这个数据包。正常情况下,发送端收到通知后,一般是从发送缓存列表中找到这个包并重新发送。可是,如果因为特定的原因,导致上次的RTT(往返延时)很大。源码中默认是100ms。

const int kDefaultRttMs = 100;

这里需要说明一点,因为WebRTC判断某个包是否超时需要重传的标准是上次的RTT时间。如果当前等待的数据包时间已经大于RTT了,就认为丢了,从而请求重传。如果小于RTT,就继续等待。那么漏洞出来了,如果上次的RTT很大很大,WebRTC确实会等待,但是出现这种情况的概率是很低的。同时,WebRTC还可以通过其他机制避免出现类似的问题,于是引出了问题三。

问题三、当大量丢包时,会全部重传吗?

答案是否定的。因为WebRTC不仅限制了重传包的次数,而且还限制了重传包的个数。WebRTC每次要求重传包的个数默认是1000个。

const int kMaxNackPackets = 1000;

如果丢失的包数量超过 1000个,会循环清空 nack_list_ 中关键帧之前的包,直到其长度小于 1000。也就是通过放弃对关键帧首包之前的老旧包的重传请求,直接而快速的请求新近的数据包,相关逻辑源码

那是不是nack_list_填充到1000个才会请求重传呢?当然不是,只要最大个数不超过1000个,就可以按照kProcessIntervalMs时间间隔请求一次重传包。即使,只丢失了一个包也会在规定的时间进行重传请求

const int kProcessFrequency = 50; const int kProcessIntervalMs = 1000 / kProcessFrequency;

其中,kProcessIntervalMs = 20ms。这里有些不理解,为什么不直接初始化20ms,却要通过1000/50计算?

NACK改进

这里需要说明WebRTC新引入的一种机制:NACK延时发送机制,通过控制NACK延时发送的时间间隔,避免固定延时网络下无必要的重传请求。比如,如果kDefaultSendNackDelayMs=20ms,如果因为网络的固有延时,造成某些数据包迟到了10ms,而此时没有NACK延时发送机制的话,这些包都会被认为丢了,从而对这些包请求重传。但是如果有20ms的NACK延时发送,这些包就不会被计算为丢失,从而避免了没有必要的重传请求,避免了资源浪费。

const int kDefaultSendNackDelayMs = 0;

而且,kDefaultSendNackDelayMs参数值是支持自定义设置的,通过接口传参field_trial设置WebRTC-SendNackDelayMs的值,WebRTC在底层会解析这个参数,如果没有设置的话,默认是10ms。相关逻辑如下:

总结

WebRTC中丢包重传逻辑是非常复杂的,本文只是简单介绍部分主要内容。好了,不早了,今天就讲到这里吧。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值