WiFi 用 CSMA/CA 代替 CSMA/CD:因为无线「听不到自己说话」,只能靠 ACK 确认。 这套规矩的代价可以逐项算出来:54 Mbps 的 WiFi,实际效率不到五成。
3.4.1 铺开了无线技术,这一节进 WiFi 的内部。 核心是「为什么无线不能做碰撞检测」,以及它为此付了多少钱。
一、为什么不能碰撞检测
因为在无线上「边发边听」做不到:
| 问题 | 有线 | 无线 |
|---|---|---|
| 听自己的发送 | 能(有独立的收线) | 不能(自己发的信号盖住一切) |
| 听别人的碰撞 | 能 | 远处站听不到,有隐藏终端 |
| 所以机制是 | CSMA/CD(检测) | CSMA/CA(避免) |
第一行是物理原因:无线只有一根天线,发的时候收不到(或者说自己发的信号太强)。 所以「撞了立刻停」这个动作在无线上根本做不到。 第二行那个「隐藏终端」更麻烦:A 和 C 都连 B,但 A 和 C 互相听不到。 于是两个都以为信道空闲,同时发给 B,在 B 那里撞了。 这个问题有线不存在(一根线上大家都能听见彼此)。 所以 WiFi 改成「避免」而不是「检测」: 发之前先约(RTS/CTS),发完必须确认(ACK),收不到 ACK 就当失败重传。 代价是「每一次成功发送都要多一个来回」。
二、效率怎么被吃掉的
一笔一笔算,54 Mbps 是怎么变成二十几的:
| 项目 | 典型值 | 说明 |
|---|---|---|
| 数据帧 | 226 微秒 | 1528 字节 ÷ 54 Mbps |
| SIFS | 10 微秒 | 短帧间隔,留给对方回 ACK |
| ACK | 144 微秒 | 18 字节,但走 1 Mbps 基本速率 |
| DIFS | 28 微秒 | 长帧间隔,让高优先级先插队 |
| 随机退避 | 67.5 微秒 | 平均 7.5 个时隙,每槽 9 微秒 |
第三行那个 ACK 最值得盯住:18 字节的帧,走 1 Mbps 要 144 微秒。 为什么要用最慢的速率发这么小的帧? 因为 ACK 必须让「所有邻居」都收到—— 用高速率发,远处的站听不见,会以为信道空闲接着发,就撞了。 所以「慢」在这里是功能,不是缺陷。 五行加起来 475.9 微秒,其中真正传数据只有 226.4 微秒:效率 47.6%。 这就是「54 Mbps 的 WiFi 实际只有二十几 Mbps」的全部原因。 不是厂商虚标,是协议为了「不撞」付掉了一半。 而且这还没算上「多个站竞争」的损耗:人一多,退避时间会变长,效率进一步下降。 所以「WiFi 标称速率」和「实际下载速度」之间,永远有一个「除以二」的关系。
三、帧格式也不一样
WiFi 的帧头比以太网长得多:
| 字段 | 以太网 | 802.11 |
|---|---|---|
| 地址个数 | 2(源、目的) | 3~4 个 |
| 帧头长度 | 14 字节 | 24 字节(最简) |
| 控制字段 | 少 | 多(持续时间、序号、更多分片) |
第一行那个「3~4 个地址」是因为「要过 AP」: 源地址、目的地址之外,还要有「这个帧是谁转发的」。 所以一个从手机到路由器的帧,头里有三个 MAC。 这就是「无线帧比有线帧重」的直接原因。 第二行那个 24 字节是「最简形式」:带上 QoS 字段就变 26,再带上「HT 控制」就更多。 所以「小包在 WiFi 上尤其吃亏」——24 字节头配 40 字节的 TCP 确认包,效率极低。 这也解释了一个日常现象: 「WiFi 打游戏延迟高」不完全是因为速率,是因为「小包要排队,每个包都要头 + ACK + 退避」。 所以「同样的带宽,包越小,WiFi 越吃亏」。
四、动手 Demo:802.11 的效率天花板——一半时间在等
把一个 1500 字节的数据帧在 54 Mbps 下发一次,逐步加开销。 重点看 ACK 那一行:18 字节为什么要占 144 微秒。
pay, hdr, fcs, rate = 1500, 24, 4, 54.0
t_data = (hdr + pay + fcs) * 8 / (rate * 1e6) * 1e6
t_ack = (14 + 4) * 8 / 1e6 * 1e6 # 控制帧走 1 Mbps
sifs, difs, slot = 10.0, 28.0, 9.0
backoff = slot * 7.5
total = t_data + t_ack + sifs + difs + backoff
print('数据帧 %.1f 微秒' % t_data)
print('SIFS %.1f' % sifs)
print('ACK %.1f' % t_ack)
print('DIFS %.1f' % difs)
print('退避 %.1f' % backoff)
print('合计 %.1f,效率 %.1f%%' % (total, t_data * 100 / total))
实跑输出:
--------------------------------------------------------------------
802.11 的效率天花板——一半时间在等
--------------------------------------------------------------------
**以太网是「想说就说,撞了再退」,WiFi 是「想说先问,问完再说」。**因为无线听不到自己的发送,
没法做碰撞检测,只能改成「先约好再发、发完等确认」。**这套规矩的代价,可以逐项算出来。**
项目 微秒 说明
-----------------------------------------------------------
发数据帧 226.4 24 头 + 1500 载荷 + 4 校验,54 Mbps
SIFS 10.0 短帧间隔,留给对方立刻回 ACK
回 ACK 144.0 18 字节,但走 1 Mbps 基本速率
DIFS 28.0 长帧间隔,让高优先级先插队
随机退避 67.5 平均 7.5 个时隙,每个 9 微秒
**合计 475.9 微秒,其中真正在传数据只有 226.4 微秒,占 47.6%。**
**这就是「54 Mbps 的 WiFi 实际只有二十几 Mbps」的原因**——
**不是厂商虚标,是协议为了「不撞」付掉了一半。**
**第二行那个 ACK 最值得盯住**:**它只有 18 字节,却要走 1 Mbps 的基本速率,占掉 144 微秒。**
**为什么要用最慢的速率发这么小的帧?**
**因为 ACK 必须让「所有邻居」都能收到**——
**用高速率发,远处的站听不见,会以为信道空闲接着发,就撞了。**
**所以「慢」在这里是功能,不是缺陷。**
**还有一个更狠的代价藏在「问」这个动作里**:
**发送前要先发 RTS、等 CTS,两来两回**——**小包在大流量网络里常常干脆不发 RTS,直接赌一把。**
**所以无线网络的实际表现高度依赖「同时在线几个站」**,**这一点和上一节共享介质是完全一样的道理。**
数据帧 226.4 微秒、ACK 144 微秒: ACK 只有 18 字节,却占了数据帧的六成时间——因为它走 1 Mbps 的基本速率。 「用最慢的速度发最小的帧」是 WiFi 里最反直觉的设计,但它是必需的:ACK 要让所有邻居听见。 合计 475.9 微秒、效率 47.6%:这就是「54 Mbps 实际二十几 Mbps」的算法。 注意这里还没算「多个站竞争」,人一多,退避时间变长,效率还会掉。 「测出来的速率只有标称的一半」不是 bug: 换成 802.11ac 的 866 Mbps 也一样,实际能到 400 多就算好。 所以看 WiFi 规格要有「除以二」的心理准备,而且这还是在「离得近、没人抢」的理想条件下。
30 秒实验
- 把速率改成 300(802.11n 两流),看效率变成多少。
- 把 ACK 的速率改成 54(假设跑高速率),效率能提高多少?为什么实际不这么做?
- 想一下:为什么「小包多的业务」(如游戏)在 WiFi 上格外吃亏?
常见误区
- 以为 WiFi 也在做碰撞检测。 它做的是碰撞避免,因为发的时候听不到自己。
- 以为 ACK 慢是设计缺陷。 慢是功能,要让所有邻居都听见,避免它们误判信道空闲。
- 以为「标称 54 Mbps」就能下到 54。 协议开销吃掉一半,实际二十几就算正常。
自测三问(点开对答案)
1. 为什么 WiFi 不能做碰撞检测? —— **因为发的时候收不到**(自己发的信号太强)。 而且还有「隐藏终端」问题:两个站互相听不到,却在同一个 AP 上撞。 2. ACK 为什么走 1 Mbps 这么慢的速率? —— **要让所有邻居都收到。** 用高速率发,远处的站听不见,会以为信道空闲,接着就撞了。 3. 54 Mbps 的 WiFi 实际效率大概多少? —— **不到五成。** 数据帧 226 微秒,总开销 476 微秒,约 47.6%。下一节看 2.4 GHz 的信道:为什么只有三个能用。
- ☐ (本节完,下一节 3.4.3 IEEE802.11b和IEEE802.11g)