共享介质的规则是「先听后说、边说边听、撞了就退」。 它的天花板不是带宽,是「人均带宽」——人越多每人越少。
3.2.1 讲的是「地址」,这一节讲「一根线怎么被多台设备分」。 用仿真跑一遍 CSMA/CD,把「站数 → 人均等待」这条曲线算出来。
一、两条路线的分岔
早期局域网有两条完全不同的技术路线:
| 路线 | 怎么做 | 代表 | 结果 |
|---|---|---|---|
| 争用型 | 谁想发就发,撞了再退 | 以太网 | 赢了 |
| 令牌型 | 拿到令牌才能发 | 令牌环、FDDI | 输了 |
第一行的优点是「空闲时零开销」:没人发的时候,线路完全不用管。 第二行的优点是「延迟有上界」:因为「什么时候轮到我」是算得出来的。 结果是争用型赢了,但赢的原因不是「更快」——令牌环在重负载下效率更高。 赢的原因是「简单、便宜、空闲时不用管」。 办公场景恰恰是「大部分时间没人发数据」。
二、CSMA/CD 的三条规矩
名字本身就是三条规矩的缩写:
| 字母 | 全称 | 动作 |
|---|---|---|
| CS | Carrier Sense | 发之前先听,有人说话就等 |
| MA | Multiple Access | 多台设备共用一条线 |
| CD | Collision Detection | 边发边听,撞了立刻停 |
第一条只能减少碰撞,不能消除: 因为「听」和「发」之间有时间差——两台站可能同时听到空闲、同时开口。 这个时间差就是「传播延迟」,它决定了「碰撞不可避免」。 第三条是「及时止损」:撞上之后立刻停,不再把整帧发完。 如果不做这一步,一次碰撞要浪费一整帧的时间,而不是几十个比特的时间。 撞了之后要「退避」:随机等一段时间再试。 等的时候线路是空着的,这就是效率损失的主要来源。 站越多,撞得越频繁,空等的时间占比越高。
三、为什么它撑不住了
三个原因,一个比一个致命:
| 问题 | 表现 | 根因 |
|---|---|---|
| 半双工 | 同一时刻只能一个方向 | 收发共用一对线 |
| 冲突域太大 | 一台说话,全部变慢 | 所有站共享一个域 |
| 人均带宽 | 人多就慢,且无法改善 | 总量固定,只能分 |
第一行是物理决定的:共享介质只有一对线,收发不能同时进行。 这就是「10BASE-T 用两对线但只跑半双工」的原因—— 早期集线器把所有口接到同一个冲突域,仍然只能半双工。 第三行是这一节的核心:不管协议怎么优化,「一根线 10 Mbps」这个总量是不变的。 所以共享介质的终点一定是「换成交换机」——把「一个冲突域」拆成「每个口一个冲突域」。 这件事在下一节讲,它就是「非共享介质」。
四、动手 Demo:共享介质里,人越多越慢——CSMA/CD 实测模拟
仿真规则:每站有帧排队;每个时隙所有有帧的站同时尝试; 只有一站尝试就发成功(占 8 个时隙),两站以上全撞(占 1 个时隙)并随机退避。 跑 2、5、10、20、50 个站,看「利用率」和「人均等待」两列的走向。
import random
def sim(nsta, per, seed=1):
rnd = random.Random(seed)
q, bo = [per] * nsta, [0] * nsta
slot = busy = ok = coll = 0
while sum(q) > 0 and slot < 400000:
slot += 1
if busy > 0:
busy -= 1
continue
want = [i for i in range(nsta) if q[i] > 0 and bo[i] <= 0]
for i in range(nsta):
if bo[i] > 0:
bo[i] -= 1
if not want:
continue
if len(want) == 1:
q[want[0]] -= 1
ok += 1
busy = 8
else:
coll += len(want)
for i in want:
bo[i] = rnd.randint(0, 2 ** min(6, coll // nsta + 1) - 1)
return slot, ok, coll
for n in (2, 5, 10, 20, 50):
slot, ok, coll = sim(n, 200)
print('%2d 站:%6d 时隙 碰撞 %5d 利用率 %5.1f%% 每帧等 %6.1f 时隙'
% (n, slot, coll, ok * 8 * 100.0 / slot, slot / 200.0))
实跑输出:
--------------------------------------------------------------------
共享介质里,人越多越慢——CSMA/CD 实测模拟
--------------------------------------------------------------------
**共享介质型网络的规则只有一条:发之前先听,听着有人说话就等。**可这条规则在人多的时候会失效——
两个人同时听、同时开口,就撞了。**下面用一个仿真把「站数 → 人均等待」这笔账算出来。**
仿真规则:每站有帧排队;每个时隙所有有帧的站同时尝试;
只有一站尝试就发成功(占 8 个时隙),两站以上全撞(占 1 个时隙)并随机退避。
站数 总时隙 碰撞次数 线路利用率 每站每帧等几时隙
-----------------------------------------------------------------
2 3886 34 82.3% 19.4
5 9934 268 80.5% 49.7
10 20307 1225 78.8% 101.5
20 41335 5336 77.4% 206.7
50 112667 48204 71.0% 563.3
**先看第四列,这一列会让人意外**:**站数从 2 涨到 50(25 倍),线路利用率只从八成多掉到七成。**
**CSMA/CD 的总效率其实是相当好的**——
**它比「谁想说就说」的纯随机接入好得多,因为「先听」这个动作省掉了大量无谓的碰撞。**
**真正崩掉的是第五列**:
**2 个站时,每站发一帧只等十几个时隙;50 个站时要等五百多个时隙,涨了近三十倍。**
**站数涨 25 倍、等待涨 30 倍、总吞吐只掉一成多**——
**这三个数放在一起,才是「共享介质」的真相:总量不变,人越多每人越少。**
**所以「共享介质的天花板」不是「总带宽不够」,是「人均带宽不够」**:
**一根 10 Mbps 的线,2 个人用各 5 Mbps,50 个人用各 0.2 Mbps**,
**不管怎么优化协议都改变不了这一点。**
**这也是为什么后来一定要换成交换机——不是协议不聪明,是「分」这件事注定不够。**
**还有一个更隐蔽的代价**:**碰撞检测要求「发的时候还能听见」**,
**所以共享介质只能半双工,而且帧不能太短**——**太短的帧在碰撞信号传回来之前就发完了,检测不到。**
**这就是以太网把最小帧定成 64 字节的真正原因**(下一节还会用到这个数)。
先看「利用率」这一列,结论会让人意外: 站数从 2 涨到 50(25 倍),利用率只从八成多掉到七成。 CSMA/CD 的总效率其实相当好——「先听」这个动作省掉了大量无谓的碰撞。 真正崩掉的是最后一列: 2 个站时每站发一帧只等十几个时隙,50 个站时要等五百多个,涨了近三十倍。 站数涨 25 倍、等待涨 30 倍、总吞吐只掉一成多—— 这三个数放在一起才是共享介质的真相:总量不变,人越多每人越少。 所以「共享介质的天花板」不是「总带宽不够」,是「人均带宽不够」: 一根 10 Mbps 的线,2 个人用各 5 Mbps,50 个人用各 0.2 Mbps, 协议再怎么优化也改变不了这一点。 这就是后来必须换交换机的原因——不是协议不聪明,是「分」这件事注定不够。
30 秒实验
- 把
per从 200 加到 1000,看利用率是否上升(重负载下退避的作用更明显)。 - 把成功率那段
busy = 8改成 1(对应 64 字节小帧),看利用率怎么变。 - 想一下:如果把随机退避去掉(撞了就立刻重试),会发生什么?
常见误区
- 以为「CSMA/CD 效率很低」。 总效率其实能到七八成,低的是「人均带宽」。
- 以为「先听」能彻底避免碰撞。 听和发之间有时间差,传播延迟决定了碰撞不可避免。
- 以为「加站只是变慢一点」。 每帧等待时间涨得比站数还快,因为碰撞概率是平方级上升的。
自测三问(点开对答案)
1. CSMA/CD 三个字母各是什么意思? —— **载波侦听、多路访问、碰撞检测。**先听后说、多台共用、边发边听。 2. 为什么共享介质「人越多越慢」? —— **因为总量固定,只能分。** 站数涨 25 倍,人均带宽掉到二十五分之一,再加上碰撞,实际更差。 3. 碰撞之后为什么要「立刻停」,而不是把帧发完? —— **为了止损。** 不停的话,一次碰撞要浪费一整帧的时间;停了只浪费几十个比特的时间。下一节看另一条路:让每个站独占一条通道。
- ☐ (本节完,下一节 3.2.3 非共享介质网络)