你有没有认真想过这么一个问题我们用手机下载一个上百兆的文件网络为什么能持续地哗哗跑而不是发一个数据包就停下来干等对方的确认答案不在什么高深的算法里就在数据链路层的差错控制机制中也就是今天要聊的连续 ARQ 协议。连续 ARQAutomatic Repeat reQuest自动重传请求并不是某一个单独协议的名字而是一类协议的总称。它解决的是在不可靠链路上如何可靠传输帧的问题——通过重传来纠正丢帧和错帧。学计算机网络的几乎都绕不开它考研、面试、笔试也爱考。但是很多初学者看教材时被滑动窗口后退N帧选择性重传序号回绕这些概念绕得头晕。我当年学这门课的时候也啃了好一阵后来发现用推演画图的方式慢慢抠其实没那么玄乎。这篇文章我会把连续 ARQ 背后的设计动机、两种核心实现后退N帧和选择性重传、窗口与序号空间的关系、以及实战中真正容易踩的坑一次性讲清楚希望你读完能建立起一个完整的画面感而不是记一堆孤立结论。1. 先看停等 ARQ 为什么慢得离谱连续 ARQ 的动机在讲连续 ARQ 之前必须先把它的前辈——停等 ARQStop-and-Wait讲透。因为你只有明白了停等的问题才能理解连续 ARQ 出现的理由。1.1 停等 ARQ 的工作原理与效率瓶颈停等 ARQ 的逻辑很朴素发送方发一帧然后停下来等待接收方的确认帧ACK只有收到 ACK才继续发下一帧如果超时比如定时器到期还没收到 ACK就重发刚才那一帧。这种方案的正确性毋庸置疑但效率在长距离、高速率链路上的表现非常难看。我当年第一次被震惊到是算一道题假设卫星链路地球站到卫星之间的单向传播时延约为 250ms那么一帧从地球发到卫星再返回地球光来回传播就是大约 500ms。如果发送一帧本身只需要 1ms那么停等协议下链路的利用率大约就是 1ms / (1ms 500ms)连 0.2% 都不到。也就是说这条昂贵的链路上 99.8% 的时间都在空等。核心问题出在串行化等待一帧的确认到达发送方之前发送方完全无法发送后续帧链路被白白浪费了。卫星通信、长距离光纤传输这种长肥管道场景停等协议简直就是灾难。1.2 连续 ARQ 的设计动机让链路忙起来既然干等确认太浪费思路就顺理成章了能不能不等前一帧的确认就在同一时刻连续发送多帧答案是可以那就是连续 ARQ。发送方一次可以发送一批帧这些帧都在网络上飞行中然后依次收到确认。这样一来链路上始终有数据在流动利用率大幅提升。但连续发送并不是白送的福利它立刻引出了两个棘手问题。第一个是如果中间某一帧丢了发送方怎么知道该重传哪一帧第二个是接收方可能收到乱序帧它该丢弃还是缓存这两个问题的不同答案就孕育出了两大流派——后退 N 帧Go-Back-N简称 GBN和选择性重传Selective Repeat简称 SR。它们都属于连续 ARQ但又各有一套处理乱序和重传的策略后面两章我会分别拆解。这里先记住一个总纲连续 ARQ 发送方拥有一个大于 1 的发送窗口 自动重传机制窗口是它的外形重传是它的灵魂。2. 滑动窗口机制连续 ARQ 的心脏和通用骨架在具体展开 GBN 和 SR 之前必须先聊清楚滑动窗口这个概念。因为不管哪种连续 ARQ底层的骨架都是同一个东西——滑动窗口。2.1 发送窗口与接收窗口一对互相制约的滑块发送窗口是指发送方此刻有权发送的帧序号集合。窗口大小为 W 时发送方最多可以连续发出 W 个尚未被确认的帧。随着 ACK 不断返回发送窗口像传送带一样向前移动这就是滑动的含义。接收窗口则是接收方愿意接收的帧序号集合。接收窗口大小为 1 时接收方只愿意按序接收下一帧任何乱序帧到达都会被丢弃接收窗口大于 1 时接收方可以暂时存下那些提前到达的帧。这两个窗口的大小直接决定了协议的性质发送窗口和接收窗口都等于 1就是停等 ARQ发送窗口大于 1 而接收窗口等于 1就是 GBN两者都大于 1 且相等就是 SR。你看教材里三个协议并不互斥它们只是同一套滑动窗口机制在不同参数配置下的变体。理解了这一点连续 ARQ 的整个体系一下子就变得特别完整。2.2 序号空间与窗口大小的约束一个隐藏的雷区滑动窗口用序号来标记帧但帧的序号字段是有限位的。若序号占 k 位则序号空间大小是 2^k序号从 0 一直到 2^k - 1用完之后绕回即取模 2^k。这时就出现一个经典问题如果发送窗口太大导致前后两批帧的序号范围出现重叠接收方将无法区分新帧和重传旧帧。为了消除歧义必须对窗口大小施加限制。停等 ARQ 序号只需 1 位窗口大小是 1GBN 要求发送窗口 ≤ 2^k - 1SR 要求发送窗口等于接收窗口且不超过 2^(k-1)。这三个约束条件不是拍脑袋定的背后有严格的推演逻辑。我在第 5 章会用具体案例详细证明这里先让大家记住这个结论避免最开始就在公式上卡住。2.3 从叫号柜台理解滑动窗口一个非常直观的类比如果你觉得窗口还是太抽象可以想象医院叫号大厅的取药窗口。患者手里的号牌就相当于帧序号发药窗口前面有一个电子叫号屏显示当前可以取药的号段这就好比发送窗口的意义只有在我许可范围内的号才有资格进入发药通道。再设想一下你正在用手机做活动抢购系统只允许同时处理 5 个未确认订单。你提交第 1 单时窗口里还有 4 个位置收到第 1 单的确认短信后窗口向前挪一格你又能提交新单了。这其实就是滑动窗口在现实生活中的翻版窗口大小决定了在途未确认数量的上限确认事件则推动窗口前移。链路层的滑动窗口和电商抢购系统里的限流窗口共享同一套思维模型——用可用的在途量来平衡效率和可靠性。3. 后退 N 帧GBN重传一切错位之后的帧后退 N 帧协议是连续 ARQ 里最经典、最常用的一种实现也是考研和面试题里的常客。它的策略用一句话概括发送方如果发现某一帧超时未确认就会重传该帧以及之后所有已经发出的帧哪怕那些帧其实都完好无损地到达了接收方。3.1 发送方行为连续发定时查出错整批撤回GBN 发送方这边有三个基本规则。第一只要发送窗口未满就可以连续发送新的帧不需要等待上一帧的 ACK。第二收到确认时采用累积确认方式——它收到的 ACK n 表示序号 n 及之前的所有帧我都已经正确收到换句话说一个 ACK 可以对多个帧起到确认作用。第三如果某帧超时就把该帧以及发送窗口内所有尚未被确认的帧全部重传。为什么叫后退 N 帧因为它不是只重传超时的那一帧而是从坏帧开始后退 N重传后面那一整串帧。举个具体例子发送方窗口大小为 5依次发出帧 0、1、2、3、4假设帧 1 在传输途中丢失了接收方只按序收到了帧 0后面帧 1 之后的帧 2、3、4 虽然其实没丢、也到达了接收方但接收方因为只按序接收所以会将它们一律丢弃。发送方等不到帧 1 的确认导致超时于是重传帧 1、2、3、4——白白浪费了后面四帧的传输机会。3.2 接收方行为按序接收乱序即丢GBN 接收方的策略非常极端而简洁接收窗口大小为 1只接受预期中的下一帧。假设接下来应该收帧 5但网络中乱序到达了帧 6接收方会直接丢弃帧 6并且重新发送一次对帧 4 的确认也就是最后一个正确接收的帧的 ACK相当于在催发送方我还在等 5后面的别着急发。这种设计的核心价值在于接收方几乎不需要缓存。任何乱序帧都在到达时被扔掉接收方的内存成本极低协议实现也非常简单。但它的代价就是在高误码率或高丢包率链路上显得反应过度一个帧丢了后面所有帧都得跟着重传。链路越长胖这种浪费越明显。3.3 GBN 的适用场景与典型考题套路从我接触过的实际教学和笔试题目来看GBN 的典型考点集中在三个地方画时间轴推演收发过程、计算发送窗口大小限制、计算信道利用率。那句需要反复强调的话是在 GBN 中接收方不给乱序帧缓存发送方重传的帧数是超时帧及其后所有已发未确认帧的总和。尽管 GBN 浪费带宽但它实现简单、接收方零缓存在对硬件成本敏感、误码率较低的链路上依然很有价值。很多简单的数据链路协议、以及一些轻量级嵌入式通信场景使用的都是类似 GBN 的思想。4. 选择性重传SR只修坏掉的那一帧GBN 那种一错全撤的做法在高质量链路上太浪费。于是就有了更精细化的方案——选择性重传SR。它的策略是发送方只重传真正超时的那一帧接收方用缓存把提前到达的乱序帧暂时收下等断档的帧补齐后按序交付给上层。4.1 SR 发送方行为逐帧定时独立重传SR 发送方和 GBN 最大的区别是它为发送窗口内每一帧都维护独立的定时器。每个帧都自求多福谁的定时器超时就单独重传谁其他帧不受牵连。同时SR 使用的确认不再只是累积确认而是逐帧确认收到 ACK n 就明确表示帧 n 我收好了发送方可以把帧 n 标记为已确认。只有当一个窗口中最前面的若干帧全部被确认后发送窗口才会向前滑动。这意味着ACK 不必按顺序到达乱序确认也能正常工作。4.2 SR 接收方行为乱序缓存凑齐交付SR 接收方的接收窗口大于 1它愿意接收发送窗口范围内任意序号的帧。如果帧 n 提前到达先把它存进缓存同时给发送方反馈对帧 n 的确认当缺口的那个帧比如帧 m终于到达时接收方会检查缓存把从 m 开始连续的一串帧一次性交付给上层并将接收窗口整体向前滑动。你可能已经发现了SR 的信息处理逻辑比 GBN精致很多但代价也很明显接收方必须准备足够的缓存用来存放那些提前到了却在等待缺口帧的数据发送方也要为窗口内每个帧维护独立的定时器状态。协议复杂度、状态机复杂度都显著上升。4.3 GBN 与 SR 的全面对比为了方便对照我把两种协议的核心差异整理成下面的表格对比维度后退 N 帧GBN选择性重传SR重传范围重传超时帧及其之后所有已发未确认帧仅重传超时的那一帧接收方缓存需求几乎不需要缓存乱序帧一律丢弃需要缓存乱序帧等待缺口补齐确认方式累积确认ACK n 表示 n 及以前都收到逐帧确认每个帧独立确认发送方定时器可只为一个帧或窗口整体设计超时管理每个帧独立定时器最大发送窗口序号占 k 位时2^k - 12^(k-1)且发送窗口接收窗口链路利用率高但受重传浪费影响更高尤其误码率较高时实现复杂度低高这张表建议你存下来或者抄一遍考前很有用。每次做场景题你只要问自己一句这个链路误码高不高接收方能做缓存吗如果网络质量差、缓存充足选 SR如果链路质量好、追求简单实现选 GBN 完全够用。4.4 一个容易翻车的隐藏细节重复帧问题SR 有一个常年被人忽略的坑当帧 n 的确认帧ACK n丢失时发送方会认为帧 n 超时并重传它。接收方此时可能已经收到了帧 n 且缓存已前移那么重传的帧 n 会让接收方产生这是新帧的错觉从而造成重复接收。为了避免这种现象SR 协议要求接收方在窗口滑动后依然能识别并丢弃那些迟到但曾经处理过的重复帧。教材上通常只给结论说窗口大小不能超过 2^(k-1)但很少解释原因——其中一部分原因正是要让新旧窗口序号区间彻底错开保证发送方和接收方永远不会把一个旧帧误判成新帧。下一章我会把这里推到最细。5. 窗口大小限制与超时重传参数最容易被扣分的实战细节这一章完全是干货中的干货也是我当年踩过最多坑的地方。很多同学背2^k - 1和2^(k-1)背得滚瓜烂熟但真遇到推导题或者变式题就傻眼。这里我把推导逻辑和实战参数都摊开来讲。5.1 序号占 k 位时GBN 窗口为什么最多是 2^k - 1我用 k2序号只能取 0、1、2、3来推演。假设发送窗口大小为 4即 2^k发送方一次发出 0、1、2、3 四个帧然后等待确认。如果这四个帧全部丢失发送方超时后重传 0、1、2、3此时接收方第一次收到的也是 0、1、2、3它无法区分这是新一批帧还是重传的旧一批——两批序号完全一样且中间没有任何信息可以区分。但如果发送窗口上限设为 3情况就不一样了第一批帧最多发出 0、1、2接收方若正确收到会回 ACK发送窗口才滑动到 3、0、1假如此时 3 丢失发送方重传 3、0、1。接收方可通过状态判断出这批 0、1 是在收到 3 之后的重传帧而不是新一轮全新帧语义不再歧义。把这种推理推广到 k 位序号就得到 GBN 发送窗口 ≤ 2^k - 1。这个减 1不是公式记忆而是为了彻底消除新旧窗口的语义重叠。5.2 序号占 k 位时SR 窗口为什么最多是 2^(k-1)SR 的情况更微妙。因为接收方和发送方窗口都大于 1接收方要给乱序帧缓存如果新旧窗口发生重叠接收方将无法区分新帧和重传帧可能把重复数据当成新数据交给上层。还是以 k2 为例。SR 窗口若为 2两个窗口之和正好是 4序号 0 和 2 被重复利用时依然能通过接收窗口位置区分新旧若窗口大于 2比如发送方发 0、1、2、3接收方也缓存 0、1、2、3那么当接收窗口滑动一圈回来时重传的 0 到底是新帧还是旧帧无法判断。对 k 位序号的通用结论就是SR 的发送窗口和接收窗口必须都小于等于 2^(k-1)且两者相等。这条约束是整个 SR 协议正确性的基石。5.3 超时重传时间RTO到底设多少才合适关于超时时间太多同学忽略它了。GBN 和 SR 都依赖定时器来触发重传而超时时间的设置本质上是与网络往返时间RTT的赌博。如果 RTO 设置得太短可能出现大量不必要的重传明明 ACK 已经在路上了只是稍微堵了一会儿发送方却急着重传反而加剧了网络拥塞如果设置得太长一旦真有帧丢失链路又要空等很久才恢复传输浪费吞吐量。比较朴素的做法是发送方持续测量 RTT 样本计算一个平滑估计值再给这个估计值乘以一个大于 1 的裕量通常取 2 左右再加上一个安全余量从而得到 RTO。更复杂一点的是在一次重传发生后暂时忽略重传帧的 RTT 样本避免把由于超时重传而导致的异常大 RTT混入正常估计行业内称之为对测量样本的规避策略。对于考试来说你至少要知道RTO 要大于平均 RTT它的大小直接决定了协议的效率实际工程里RTO 的合理性往往比窗口大小更影响用户体验。5.4 场景题速判长肥管道该用什么假设一条 10Gbps 的长距离链路单向传播时延 20ms误码率极低你该选 GBN 还是 SR我的建议是 GBN因为误码极低时重传几乎不会发生GBN 的整批重传缺点被规避而它的简单性优势被凸显。反过来如果一条低速但干扰严重的无线链路丢包率偏高那一定要用 SR否则频繁整批重传会直接把链路利用率打成筛子。这道题的背后是工程权衡在指标可预测的稳定链路上简单方案往往表现优秀在不确定、高动态的信道上复杂的容错机制才有用武之地。6. 学习连续 ARQ 的实操方法与高频考点避坑指南最后聊聊我自己的学习路径和踩坑经验这部分在教材上基本找不到但非常适合备考或者项目里临时需要补网络基础的人。6.1 拿起纸笔画一张收发时间轴胜过看十遍书连续 ARQ 最大的入门障碍是脑子里没有画面。我建议你用一张白纸横轴是时间纵轴分两行——上面一行画发送方的发送事件下面一行画接收方的确认事件。然后取很小的窗口比如窗口 4序号 0-7手动模拟一帧丢失、一帧 ACK 丢失这两种情况把每一步的状态变换写下来。这个动作我做过不下十遍。做完之后你会发现GBN 的超时重传逻辑和 SR 的独立重传逻辑不再是两条抽象规则而是变成了你脑子里的动画。以后再遇到复杂的题目你完全可以在草稿纸上复现这个过程而不是凭空想象。6.2 高频考点避坑清单这些错我几乎年年见误区一GBN 和 SR 都缓存乱序帧。错。GBN 不缓存乱序帧一律丢弃只有 SR 才缓存。误区二SR 的 ACK 是累积式的。错。SR 走逐帧确认路线GBN 走累积确认路线。误区三窗口越大一定越好。错。窗口越大在途数据越多一旦出错重传代价也越大而且窗口大小还受序号空间约束不是想开多大开多大。误区四只背公式不理解 2^k - 1 和 2^(k-1)。错。考试一旦换一种问法比如序号占 3 位SR 最大窗口是多少或者给定窗口和链路容量至少需要几位序号死记硬背的人直接翻车。理解了窗口与新旧帧区分的关系这种题就是送分题。误区五把 ACK 丢失等同于帧丢失。GBN 中如果某个帧的 ACK 丢了只要后续有更新的 ACK 到达累积确认的语义就能让它顺带确认前面的帧所以单丢一个 ACK 并不必然触发重传。这也是累积确认的一个隐藏优点。6.3 一种超实用的窗口-序号-链路利用率联动计算方法考试和面试里最高频的一道计算题是给定链路长度、速率、帧长问你采用 GBN或 SR时通道的最大利用率是多少。这类题我建议按三步走第一步求出发送一帧所用的时间帧长除以数据速率第二步求出单程传播时延再乘 2 加上确认帧发送时间得到一帧从发出到收到确认的完整周期第三步用窗口内连续发送的帧数 × 单帧发送时间占整个周期的比例就是链路利用率的大致估值。当然如果为了达到 100% 利用率发送窗口必须大到在第一个 ACK 到达前就能把所有帧发完于是就可以反推出最少需要的窗口大小和序号位数。我在帮人讲题时发现很多人不是不会公式而是没搞清楚发送时延和传播时延的区别。记住一句话发送时延是路由器把帧倒进链路需要的时间取决于帧长和速率传播时延是比特在链路上跑完需要的时间取决于距离和介质速度。这两个概念混了所有链路利用率计算题都会错。如果在项目或实验里想看看真实网络中的重传行为可以用抓包工具观察某条 TCP 连接里出现重复 ACK 和快速重传的情况——虽然 TCP 的重传机制和数据链路层的连续 ARQ 不完全一样但你能从中真实感受到重传是可靠传输的兜底手段这句话的分量。用理论反推实际再用实际验证理论这是我学网络这么多年最有效的一招。说回连续 ARQ 本身它不是一个需要死记的孤立知识点而是理解整个可靠传输体系的一把钥匙。数据链路层的 GBN、SR到传输层的 TCP 滑动窗口和选择性确认本质上都在回答同一个问题——如何用有限的序号空间、合理的窗口大小、聪明的确认策略在不可靠的信道上实现高速可靠的传输。把连续 ARQ 这个地基打扎实了后面看 TCP 的拥塞控制、乱序缓存、快速重传都会觉得异常亲切。希望这篇从设计动机到推导细节再到做题技巧的全过程拆解能帮你把这块硬骨头真正啃下来。