同一房间里增加几个无线发送者,为什么一个小请求也可能等待更久?无线链路除了发送数据,还需要决定谁在什么时间占用共享介质。应用没有增加负载长度,等待介质、失败后的重试和重新竞争仍然可能改变完成时间。

第 01 篇分开了发送、传播与排队时延,第 04 篇观察了交换端口的转发范围。本篇增加介质竞争这一条件,用一个有界模型比较单发送者和多个竞争者。模型没有操作无线网卡,也不是完整的 IEEE 802.11 实现;所有时间数字都是模型单位,不能换算为真实 Wi-Fi 吞吐。

交换端口与共享介质

第 04 篇的实验从一个网桥入口选择出口,解决的是帧应该转发到哪里。即使目的地已经明确,发送者仍要获得底层介质的使用机会。Wi-Fi 的多个站点可能竞争同一信道,AP 本身也需要参与相应的介质访问过程。

讨论经典分布式协调功能 DCF 时,发送资格与载波侦听、帧间间隔和退避计数有关。不能把一条应用消息已经排到网卡队列前端,等同于它马上开始在无线介质上传输。

现代 Wi-Fi 还有优先级、聚合、多用户调度等机制。为了隔离基本因果,本篇只讨论共享介质竞争的一个简化视角,不把它作为所有制式、所有工作模式的完整模型,也不罗列未经本次核查的标称速率。

侦听之后仍然可能同时发送

若两个站点都在等待介质空闲,介质刚恢复空闲时,它们可能同时具备发送意愿。只要求“先听一下”,并不能保证只有一个站点在同一时刻开始。随机退避把资格分散到多个候选时隙,以减少相同起点的机会。

RFC 8325 §6.1描述了 DCF 的时隙、帧间间隔与竞争窗口。退避计数从零到 CW 的整数中选择,两端都包含。因此 CW 为 3 时有四个候选值:0、1、2、3,不是三个。

设两个站点独立、均匀地从这四个值中选择。共有十六种有序组合,其中四种相同,初始计数相同的概率为四分之一。这只是一次抽样的手算,尚未包含介质冻结、其他站点或失败后的新窗口,不能直接写成某张网卡的碰撞率。

竞争窗口扩大后,相同计数通常更难碰到,但空闲等待可能增加。这是减少同步竞争与增加等待之间的具体代价。若以候选数量翻倍,包含端点的窗口公式应写为:

1
CW_next = min(2 × (CW + 1) - 1, CW_max)

本篇模型从 CW=3 开始,依次扩到 7、15、31。它们是教学参数,不是所有无线设备都采用的默认值。

忙时冻结,空闲后继续

退避计数不是不管介质状态都持续走完的普通定时器。经典竞争机制在介质忙时冻结剩余计数,满足相应空闲条件后再继续。否则一个站点在别人发送期间把计数耗尽,就会在仍然忙时强行开始。

手算一个简化例子:A 的计数是零,B 的计数是二。A 获得本轮发送资格,占用介质五个模型单位;这期间 B 仍保持二。A 结束后,再经过两个空闲槽,B 才到零并开始。本篇脚本用确定性用例检查这一点。

实际规则比这个例子细致。ns-3 官方设计文档引用 IEEE 802.11 条文,区分已有退避计数、物理或虚拟载波侦听以及取得发送资格的条件。因此不能概括成“每个新帧都必须重新抽一个随机数再发”。附件为了容易推演,恰好采用了每个新帧重新抽数的简化规则,不能据此声称逐条实现 DCF。

未收到确认与重传

一个发送者没有按预期收到确认,能够观察到的是这次交换尚未得到所需确认。真实环境下,数据碰撞、信道误码、接收端未解码和确认帧丢失等都可能造成这种结果;仅凭发送侧重试计数无法唯一确定根因。

本篇模型刻意排除误码和确认帧独立丢失:同一轮恰好一个发送者取得资格就成功,两个及以上同时取得资格则全部失败。模型里的失败因此可以称为碰撞,但这个等价关系是模型假设,不能移到真实无线日志上。

失败也不能无限重试。模型为一帧最多允许四次发送尝试;失败后扩大窗口,达到第四次失败就丢弃这一帧并处理下一帧。成功或丢弃后窗口恢复为三。实际标准与设备的重试规则可能区分不同情况,本篇的四次上限只是显式的实验约束。

重试消耗介质时间,却未增加成功交付的帧数。比较结果时必须同时列出完成、丢弃和未完成数量。如果一组实验更早结束,只是因为它更早丢弃了大量帧,就不能把较短运行时间称为更好的交付性能。

隐藏终端改变了谁能侦听谁

载波侦听是局部观察。设 A 和 C 都能向 B 发送,但 A、C 彼此听不到。A 判断本地介质空闲时,C 可能已经向 B 发送;两份信号在 B 附近重叠,本地空闲判断因此不能排除接收端的干扰。

1
2
A  ──可达──  B  ──可达──  C
└──────── A 与 C 彼此不能可靠侦听 ────────┘

这个拓扑条件称为隐藏终端问题。它不是简单的“用户数量多”,也不能通过同属一个 AP 就排除。是否彼此可听与传播环境有关,本篇没有射频测量,图中可达关系是用于解释机制的假设。

RTS/CTS 让短控制交换先传达占用信息,能帮助收到相关控制帧的站点推迟发送。它也增加控制开销,RTS 本身仍可能碰撞,隐藏站是否能听到 CTS 等条件也会影响效果。因此不能写成开启 RTS/CTS 就消除了全部隐藏终端问题。

附件模型假定所有发送者都能知道介质忙闲,只有在同一轮同时取得资格时才碰撞。它没有实现隐藏终端、RTS/CTS 或虚拟载波侦听。把模型的碰撞数字用于评价这些机制,超出了程序实际表达的条件。

一个能复跑的有界竞争模型

附件 model.py 使用 Python 标准库。总负载固定为三十帧:单发送者持有三十帧,多发送者为三个站点各十帧。所有帧具有相同的抽象发送成本,成功轮和碰撞轮都占五个模型时间单位。

1
python3 source/_posts/2026-09-19-计算机网络05-Wi-Fi为什么不同于网线/model.py --seed 20260919

每次循环先找仍有积压、计数为零的站点。没有站点到零时,消耗一个空闲槽,并把活跃站点的计数减一;存在到零站点时,处理一次忙轮,其他站点的计数保持原值。成功者移除一帧,碰撞参与者更新失败次数和窗口,然后为仍需处理的帧抽取计数。

成功与碰撞采用相同的五单位成本,是为了把成本变化集中到额外轮次和空闲槽上。模型没有把数据时长、ACK 超时、不同帧间隔分别还原,也没有模拟信道传播。它能回答“这组规则如何累计等待”,不能预测某个真实数据帧的空口时长。

事件循环最多执行二万次。达到上限仍有积压时,结果明确标记 capped 并报告 pending,不能把未完成部分悄悄当成丢包。程序始终检查守恒式:

1
初始帧数 = 成功完成 + 明确丢弃 + 仍未完成

本次在 Python 3.14.4 上得到以下结果,完整输出保存在 result.json。随机种子只保证在指定程序与运行条件下可复跑,不代表随机结果具有真实无线统计意义。

模型场景 完成 / 丢弃 / 未完成 碰撞轮次 空闲槽 忙时间单位 合计时间单位
一个发送者,三十帧 30 / 0 / 0 0 32 150 182
三个发送者,各十帧 30 / 0 / 0 3 48 165 213

单发送者没有竞争对象,碰撞为零是规则直接保证的。三发送者这一种子中有三次碰撞,因此忙时间增加十五单位;空闲槽又增加十六,合计多三十一单位。这个差额有可追溯的组成,而不是把“无线更慢”作为未经分解的结论。

程序还运行种子零到九。十次的碰撞轮次为 4、6、9、5、3、11、6、5、5、5;其中种子零丢弃一帧,种子五丢弃两帧。这说明单次种子不能代表所有运行,也说明比较完成时间时不能忽略丢弃量。这十个种子没有构成置信区间,更不支持设备之间的性能排名。

确定性检查与反例

模型包含三项不依赖随机“碰巧发生”的检查。两个站点初始计数都为零、每帧仅允许一次尝试时,必须出现一次碰撞并丢弃两帧;单站点初值三、事件上限一时,必须保留一帧待处理;初值零和二时,必须观察到忙轮没有扣减另一站点的计数。

这些检查验证的是代码是否执行明示规则。它们没有验证无线驱动或协议实现。模型也没有用断言要求“多个发送者在所有种子下总耗时必然更长”,因为多个计数器并行竞争时,空闲等待的组合与单站点连续抽样并不相同;碰撞成本和空闲时间都需要具体计算。

手算练习。 两个独立站点从零到七均匀抽取初值,同值概率是多少?若窗口写作 CW=7,为什么不能把答案写成七分之一?

核对:八个候选值产生六十四种有序组合,八种相同,概率为八分之一。这个概率仍然只描述初始抽样相同,不是整个连接的失败概率。

证据练习。 一台设备重试增加,是否足以证明附近有隐藏终端?如果增加 RTS/CTS 后完成时间反而增长,是否足以证明 RTS/CTS 实现错误?

核对:两项都不充分。重试还可能来自其他无线错误;控制交换本身有开销,缺少适用的竞争条件时可能得不偿失。应补充接收端证据、无线环境和受控对照,而不是从单个计数推导唯一原因。

验证边界与一手资料

本次完成了有界竞争模型、三项确定性检查、固定种子对照及十个补充种子运行。没有发送真实无线流量,没有验证无线吞吐、隐藏终端、RTS/CTS 或真实端到端通信。后续出现 Wi-Fi 环境参数时,需要重新测量,不能把本篇单位当作微秒。

以下资料于 2026-09-19 写作当次核查。实现文档和模拟案例用于说明规则及限制,其结果没有被移植成本篇实测。