谈谈网络通信中的 ACK、NACK 和 REX

article/2025/10/6 16:27:34

目录

名词解释

问题 1: 接收方如何判断数据包是否丢失?

问题 2:发送方如何确认数据包已经丢失?

问题 3:重传超时的计算规则?

问题 4:发送方的数据包要缓存多久?

问题 5:接收端多久发送一次 nack 请求?

问题 6:哪些丢失的数据包会放入 nack 请求队列中?

问题 7:如何防止某个数据包频繁的 nack 请求?

问题 8:重传包的优先级?FEC 包是否需要重传?

问题 9:RTCP 协议的 NACK 报文是如何定义的?

 

名词解释

ACK:Acknowledgement,它是一种正向反馈,接收方收到数据后回复消息告知发送方。

NACK:Negative Acknowledgement,则是一种负向反馈,接收方只有在没有收到数据的时候才通知发送方。

REX:Retransmission,重传,当发送方得知数据丢失后,重新发送一份数据。

 

问题 1:接收方如何判断数据包是否丢失 ?

v2-bd7fc27d77a92a81e1335bec8b8abb7e_hd.png

解决方案:编号,每一个 packet 都打上一个序列号(Seq number),接收端发现序列号跳变/缺失,则可以判断数据包丢失了。

这就是为什么 TCP 协议的包头(packet header)里面要定义一个序列号字段的原因(如图红色标记):

v2-eb978203bbaf84308d5feab3032eda6f_hd.png

扩展一下,我们再看看 UDP 协议的包头(packet header)的定义:

v2-3b295afec2a4779fc8ac29aad2ed5318_hd.png

可以看到,UDP header 没有用任何字段来标识序列号(Seq number),由此可见,UDP 是一个完全不关心是否丢包的传输协议。

 

问题 2:发送方如何确认数据包已经丢失 ?

有几种常见的方案,这里先简单介绍下,不详细展开细节。

 

1. 停等协议

发送方每次只发送一个包,同时启动一个定时器。如果定时器超时依然没有收到这个包的 ACK,则认为丢包,重传这个包。如果收到 ACK,则重置定时器并发送下一个包。

问题:丢包的判断和传输效率非常低。

 

2. 连续 ARQ 协议 & 滑窗协议

发送方维持着一个一定大小的发送窗口,位于发送窗口内的所有包可以连续发送出去,中途不需要依次等待对方的 ACK 确认。

接收方通常采用 积累确认模式,即不必对每一个包逐个发送 ACK,而是在连续收到几个包后,对顺序到达的最后一个包序号发送 ACK,表示:这个包及之前的所有包都已正确收到了。

积累确认模式 的缺点:乱序比较严重的网络下,效率非常低,部分已经送到但没有按照顺序送达的包也必须重传。

改进方案:选择性重传(注:KCP/SRT 协议有实现):对于顺序的包,发送积累确认;跳跃的包,发送 ACK;发送端只重传真正丢失的数据包。

 

3. 快速重传

使用 ACK 机制的传输协议,通常在发送端等到某个数据包的 ACK 超时后,才会重传数据包,不够及时。

快速重传:如果接收端接收到了序号跳跃的数据包,则立即给发送方发送最后一个连续的数据包的 ACK(重复确认) 。如果发送端收到连续 3 个重复确认,则认为该 ACK 的下一个数据包丢失了,并立即重传该丢失的数据包。

 

4. NACK

接收方定时把所有未收到的包序号通过反馈报文通知到发送方进行重传。

带来的改进:减少的反馈包的频率和带宽占用,同时也能比较及时地通知发送方进行丢包重传。

 

问题 3:重传超时的计算规则 ?

RTO:重传超时时间(Retransmission Timeout),它是发送端用来判断数据包丢失和执行重传的最重要的一个参数。

很明显,它应该是一个随网络传输的 RTT(往返时间)而变化的值,理想情况下,RTO 的值不小于 RTT 即可(从数据包发送到对方的 ACK 到达的最短时间),实际情况下,RTT 变化是非常频繁的,每一次传输的 RTT 可能都不一样,如果粗暴地设置 RTO = RTT 则一定会导致重传过度频繁。

因此 TCP 协议采用的 RTO 计算方法是:

1. 基于多次 RTT 测量,给出一个平滑后的 RTT 预估值:SRTT(Smoothed Round Trip Time)

2. RTO = SRTT + 某种系数(防止抖动的阈值)

3. 进一步,系统级别设置 RTO 的下限为 100ms 或 200ms,防止异常值

4. 更进一步,对于重传包的 RTO,加上一个退避算法,比如,每重传一次,则 RTO = 2 RTO 这样的方式来减少对一个包进行频繁的重传

注:关于重传包 RTO 的退避策略,KCP 经过实验证明 ,RTO 的退避系数使用 1.5 倍的效果比 2 倍的效果更好。

 

问题 4:发送方的数据包要缓存多久 ?

v2-657e8ec469ad6ad41bd9470ca618099c_hd.png

发送端为了能实现重传,必须在本地将发送的数据包缓存起来,在需要重传的时候,即可从缓存队列里面取到该数据包进行重传。

对于 ACK 模型的传输协议(如:TCP),在收到对方的 ACK 之后删除缓存即可,那如果是 NACK 模型的传输协议,如何更新和清理这个缓存队列呢 ?

 

1. 方案一:基于 RTT 和 NACK 时间间隔

 

假设当前的 RTT(网络往返时间)是  rtt ms,NACK 的反馈时间间隔是 x ms,那么,一个数据包在发送缓存队列中最少的存活时间应该是:

cache time = 2 * rtt + x

假设在这个时间后内收到的 NACK 反馈包没有指出该数据包丢失,则可以删除了。当然,类似 RTO 所涉及到的问题原因,rtt 是频繁变化的,因此单纯依靠这个理论值来删除缓存并不安全,建议增加一定的冗余。

 

2. 方案二:基于业务场景

 

对于实时音视频通信场景,对延时有一定的要求,因此,超过 1s 的数据,就没有必要再重传了。或者,假设视频的 GOP 是 2s,那么,最多在缓存队列保持 2s 的数据包即可。

 

问题 5:接收端多久发送一次 nack 请求 ?

假设接收端发现数据包发生序列号跳跃后立即发送 NACK 请求,由于 UDP 数据包可能会乱序到达,因此这种方案会导致过多的无效重传请求。

更加合理的方案是:每间隔指定的时间(比如:WebRTC 使用的是 10ms)发送一次 NACK 请求,一次性带上这段时间所有的丢包序号。

 

问题 6:哪些丢失的数据包会放入 nack 请求队列中 ?

接收端的重传请求的队列也应该有一定的机制,不是所有的丢包都必须要求重传,比如:

1. 当前音频播放到了 timestamp 为 x 的时间点了,其实在 timestamp < x 的所有丢失的音频包都不应该再请求重传了,视频也是如此。

2. 作为 SFU 中转服务器,它没有播放时间的概念,因此方法 1 并不适用,但是可以参考发送端缓存的逻辑,假设 GOP 是 2s,则对比最新的 packet 时间戳,丢失的数据包时间在 2s 之前的数据,则没有必要再申请重传了。

补充一点,作为 SFU 中转服务器,可能会遇到下述情况,即:收到客户端的 NACK 请求的数据包不再自己的 cached packet list 里面:

v2-315b346666c5c617f019aa3203210561_hd.png

SFU 作为客户端上行的接收端,发现丢包也跟普通的接收端一样,定时主动地向源头发送 NACK 请求;反过来,SFU 作为客户端下行的发送端,收到 NACK 请求后,如果发现不在 cached list,则标记一下,一旦收到源头的重传,则第一时间转发到下行。

 

问题 7:如何防止某个数据包频繁的 nack 请求 ?

参考 WebRTC 的实现,有如下防止策略:

1. 当一个丢失的包被 NACK 请求重传了至少 N 次(如:10次)后依然没有成功收到,则应该放弃了(很可能发送端也已经没有这个数据包的缓存了)

2. 考虑到重传请求在发送端的响应时间及网络 RTT,接收端应该确保在一定时间周期内不要频繁地发送对同一个数据包的 NACK 重传请求。(如:WebRTC 选择的时间周期是 5 + RTT * 1.5),即:在这个时间周期内不再重复发送同一个数据包的 NACK 请求。

3. 当 nack reqeust list 里面的数据包太多了(比如:超过 1000),则应该考虑清理一下(网络太弱了),对于视频的话,直接发送 IDR request,重新申请新的 GOP 数据。

 

问题 8:重传包的优先级?FEC 包是否需要重传 ?

考虑到丢包 -> 重传已经耽误了数据包的达到时间了,因此,重传包的优先级应该大于普通的数据包,当然,也应该有根据重传次数优先级逐步递减的策略。

FEC 包不需要,意义不大,FEC 的目的是为了减少重传而增加的冗余包,丢掉没有致命的影响,我们只需要重传价值更大的数据包即可。

 

问题 9:RTCP 协议的 NACK 报文是如何定义的 ?

NACK 报文的定义在 [rfc4585] 文档中定义。

RTCP 的反馈报文包头定义如下,FMT 和 PT 决定了该报文的类型,FCI 则是该类型报文的具体负载:

v2-855bbe688464b97460cd0c313d1488fe_hd.png

协议规定的 NACK 反馈报文的 PT= 205,FMT=1,FCI 的格式如下(可以附带多个 FCI,通过 header 的 length 字段来标示其长度):

v2-009b6ba8d39a2839cff34ecf0dd50222_hd.png

这里的设计比较巧妙,它可以一次性携带多个连续的数据包的丢包情况:

  • PID(Packet identifier),即为丢失的 RTP 数据包的序列号

  • BLP(Bitmao of Lost Packets),通过掩码的方式指出了接下来 16 个数据包的丢失情况


http://chatgpt.dhexx.cn/article/GPI83kwN.shtml

相关文章

费马定理_高数_1元微积分

定理 设 f(x) 在 x0 点处满足&#xff1a;1、可导 2、取得极值&#xff0c;则有 f ’ (x0)0 证明 不妨假设 f(x) 在点 x0 处取得极大值&#xff0c;则存在 x0 的邻域 U( x0 )&#xff0c;对任意的 x属于U( x0 )&#xff0c;都有 根据导数定义与极限的保号性有 又 f(x) 在点…

老猿Python博客文章目录索引

本目录提供老猿Python所有相关博文的一级目录汇总&#xff0c;带星号的为付费专栏&#xff1a; 一、专栏列表 本部分为老猿所有专栏的列表&#xff0c;每个专栏都有该专栏置顶的博文目录&#xff1a; Python基础教程目录PyQt入门学习* 使用PyQt开发图形界面Python应用PyQtmo…

(组合数+快速幂+lucas+费马小引理)acwing 887. 求组合数 III

887. 求组合数 III 题目链接https://www.acwing.com/problem/content/889/ 题目&#xff1a; 思路&#xff1a; #include<iostream> #include<cstdio> using namespace std; typedef long long LL; int n; int qmi(LL a,int k,int p){int res1;while(k){if(k&…

(组合数 +快速幂+逆元+费马小引理)acwing 886. 求组合数 II

886. 求组合数 II 题目链接https://www.acwing.com/problem/content/888/ 题目&#xff1a; 思路&#xff1a; #include<iostream> #include<cstdio> using namespace std; typedef long long LL; const int mod1e97;//mod为质数 int a,b,n; int fact[100010],…

Leetcode-数学费马平方和定理-633. 平方数之和

题目633. 平方数之和&#xff1a; 题解&#xff1a; 1&#xff0c;暴力枚举sqrt class Solution { public:bool judgeSquareSum(int c) {if(c < 2 ){return true;}for(long a 0; a*a < c; a){double b sqrt(c - a * a);if((int)b b){return true;}}return false;} …

费马定理、罗尔中值定理、零点存在定理、拉格朗日中值定理、

介值定理 介值定理如果AB,则开区间&#xff08;a,b&#xff09;内可能取不到端点值A,B 即介值定理如果C不等于端点值&#xff0c;那么 ξ ξ ξ可以是属于开区间&#xff0c;如果C等于端点值&#xff0c;那么 ξ ξ ξ必须属于闭区间。 零点存在定理 假设函数f(x)在闭区间[a,…

费马引理的证明

设 f(x)在 ξ处最大&#xff0c;故不论Δx是正或负&#xff0c;总有 设 &#xff0c; 则 。 故由极限的保号性有 &#xff08;1&#xff09; 而当 时&#xff0c; &#xff0c; 故 &#xff08;2&#xff09; 由(1)&#xff0c;(2)两式及 存在知&#xff0c;必有 设 f(x)在 ξ处…

费马引理

转载于:https://www.cnblogs.com/fuhang/p/7976329.html

高等数学——微分中值定理

本文始发于个人公众号&#xff1a;TechFlow&#xff0c;原创不易&#xff0c;求个关注 今天和大家回顾一下高数当中的微分中值定理&#xff0c;据说是很多高数公式的基础。由于本人才疏学浅&#xff0c;所以对于这点没有太深的认识。但是提出中值定理的几个数学家倒是如雷贯耳&…

(机器学习、人工智能数学基础:高等数学篇)第三章:微分中值定理:第一节:微分中值定理

文章目录 一&#xff1a;费马引理二&#xff1a;罗尔定理三&#xff1a;拉格朗日中值定理四&#xff1a;柯西中值定理五&#xff1a;泰勒公式&#xff08;1&#xff09;泰勒公式&#xff08;2&#xff09;常见泰勒展开式 一&#xff1a;费马引理 费马引理&#xff1a;如果函数…

高等数学(总结1-导数的几个定理)

1&#xff09;费马引理&#xff1a; 证明的关键&#xff1a;如果在x0处可导&#xff0c;则在x0处的左导数等于右导数等于导数。 意义&#xff1a;显然(x0&#xff0c;f(x0))是f(x)在x0邻域内的一个极值点&#xff0c;推广&#xff1a;f(x)的极值点&#xff08;驻点&#x…

人工智能数学基础:费马引理、罗尔定理、拉格朗日微分中值定理、柯西中值定理

一、费马&#xff08;Fermat&#xff09;引理 费马&#xff08;Fermat&#xff09;引理&#xff1a;设函数f(x)在点x0的某邻域U(x0)内有定义&#xff0c;并且在x0处可导&#xff0c;如果对任意的x∈U(x0)&#xff0c;有f(x)≤f(x0)(或f(x)≥f(xo))&#xff0c;那么f’(x0)0。 …

nmon结果分析工具_使用nmon analyzer 分析指标

监控结果分析 使用nmon analyser对nmon文件进行解析&#xff0c;生成带图表信息的xlsx格式文件。 下载地址&#xff1a;http://nmon.sourceforge.net/pmwiki.php?nSite.Nmon-Analyser nmon analyser转换数据 进入工具目录&#xff0c;双击nmon analyser vxx_x.xlsm格式文件&…

Linux数据存储监控工具 - nmon

nmon介绍 nmon 是 IBM 公司开发的 Linux 性能监控工具&#xff0c;可以实时展示系统性能情况&#xff0c;也可以将监控数据写入文件中&#xff0c;并使用 nmon 分析器做数据展示。 nmon 可监控的数据类型 CPU使用率内存使用情况磁盘适配器文件系统中的可用空间页面空间和页面速…

nmon下载及使用方法

nomn官方文档&#xff1a;http://www.ibm.com/developerworks/cn/aix/library/analyze_aix/ nomn下载页面&#xff1a; AIX:https://www.ibm.com/developerworks/community/wikis/home?langen#!/wiki/Power%20Systems/page/nmon Linux: nmonanalyser 下载页面&#xff1a;http…

nmon使用及监控数据分析

【使用】 【监控数据分析】 参考链接&#xff1a;nmon监控数据分析 性能测试中,各个服务器资源占用统计分析是一个很重要的组成部分,通常我们使用nmon这个工具来进行监控以及监控结果输出。 一、在监控阶段使用类似下面的命令 ./nmon -f write_3s_20vu.nmon -t -s 30 -c 100 进…

NOMSQL数据库之Mongodb

一、业务需求 用户访问日志是在web服务器access.log存储 cat access.log | awk {print $1} | uniq -c | sort -nr 查看访问次数最多的ip(百万次访问24小时) 统计每日访问量&#xff0c;峰值访问量 把每次访问存储到mongodb中,mongodb用来筛选日志 二、Mongodb介绍 1、nosql介绍…

nmon的使用方法

一、认识nmon 1、简介 nmon是一种在AIX与各种Linux操作系统上广泛使用的监控与分析工具&#xff0c;它能在系统运行过程中实时地捕捉系统资源的使用情况&#xff0c;记录的信息比较全面&#xff0c;并且能输出结果到文件中&#xff0c;然后通过nmon_analyzer工具产生数据文件与…