Appearance
以太网与交换机
概念
以太网(Ethernet)是当今占绝对主导地位的局域网技术标准(IEEE 802.3),它用 CSMA/CD 在共享介质上跑,用 48 位 MAC 地址标识站点。
一句话说清它是什么:以太网 = "规则最简单、最便宜、最能兼容升级"的那套局域网做法——它从 1970 年代的 2.94 Mbps 共享总线,一路演进到今天的万兆全双工交换式网络,靠的就是"不推倒重来"。
"以太"这个名字的来历:早期物理学假设光传播需要一种介质,叫"以太"(ether)——以太网的设计者把"数据靠电磁波在以太里传播"这个意象借了过来。 今天以太当然不存在,但名字留下了。
以太网的三个关键特征(贯穿全章):
| 特征 | 说明 |
|---|---|
| 无连接、不可靠 | 发送前不建立连接;接收方校验失败就直接丢帧,不通知发送方、也不要求重传——可靠性交给上层(TCP)保证 |
| 用 MAC 地址寻址 | 48 位平面地址,与"位置"无关(对比 IP 地址是"层次地址",见 net/30-ip.md) |
| 曼彻斯特编码起步 | 10BASE-T 用曼彻斯特编码,所以需要 20 MHz 带宽(见 net/10-physical.md) |
⚠️ "以太网不保证可靠"是常考的一句结论:收到坏帧就悄悄丢掉,是"端到端原则"的体现——链路层只管"尽量送",端到端的可靠性由 TCP 负责(这样中间设备才能做得很便宜、很快)。
与上一章(net/23-csma.md)的衔接:上一章讲"共享信道怎么抢",本章讲"抢到之后这个帧长什么样、交换机怎么把它送到该去的地方"——上一章的"最小帧 64 B"在本章变成"帧长合法性检查"的第一条规则。
原理
一、以太网的演进:从共享总线到全双工交换
命名规则:"速率 + BASE(基带)+ 介质/距离"——例如 10BASE-T 读作"10 Mbps、基带传输、双绞线"。
| 标准 | 速率 | 介质 / 拓扑 | 编码 | 最大网段 | 备注 |
|---|---|---|---|---|---|
| 10BASE-5 | 10 Mbps | 粗同轴,总线 | 曼彻斯特 | 500 m | 早期骨干 |
| 10BASE-2 | 10 Mbps | 细同轴,总线 | 曼彻斯特 | 185 m | 便宜,俗称"细缆" |
| 10BASE-T | 10 Mbps | 双绞线,星型(集线器) | 曼彻斯特(需 20 MHz) | 100 m | 站点改用双绞线接集线器 |
| 100BASE-TX | 100 Mbps | 双绞线(Cat5),星型(交换机) | 4B/5B | 100 m | 快速以太网;争用期缩到 5.12 μs |
| 1000BASE-T | 1000 Mbps | 双绞线(Cat5e/6) | 8B/10B 类 | 100 m | 千兆;全双工为主 |
| 10GBASE-T | 10 Gbps | 双绞线(Cat6a/7) | 复杂编码 | 100 m | 万兆;全双工,不再用 CSMA/CD |
⚠️ 三个阶段的分水岭:
- 总线时代:同轴电缆一根到底,所有站共享 10 Mbps,冲突频繁——这是"共享式以太网"。
- 集线器时代(10BASE-T):拓扑变成星型,但集线器是物理层设备,内部仍是"共享总线",冲突依旧。
- 交换机时代(100BASE-TX 之后):交换机按 MAC 地址转发、每个端口独享带宽;全双工模式下端口之间根本不会冲突,CSMA/CD 退居次要地位——这是"交换式以太网",也是今天的样子。
"编码方式"与速率的配合关系(回顾 net/10-physical.md):曼彻斯特效率 50% → 10 Mbps 需 20 MHz 带宽;4B/5B 效率 80% → 100 Mbps 需 125 MBaud——"为什么 100BASE-TX 用 4B/5B 而不是曼彻斯特"的答案就是"双绞线的可用带宽不够"(20 MHz 已经是极限,200 MHz 拿不出来)。
二、MAC 地址:48 位平面地址
MAC 地址(物理地址)长 48 位(6 B),通常写成 12 个十六进制数、用连字符或冒号分隔,例如 00-0C-29-11-22-33。
text
48 位 MAC 地址 = 前 24 位 组织唯一标识符 OUI + 后 24 位 厂商自行分配
┌────────────────────────────┬──────────────────────────┐
│ OUI (由 IEEE 统一分配) │ 厂商分配的序列号 │
└────────────────────────────┴──────────────────────────┘★ 单播 / 组播 / 广播的判别(必背):
| 类型 | 判别方法 | 例子 |
|---|---|---|
| 单播(unicast) | 首字节的最低有效位 = 0 | 00-0C-29-11-22-33 |
| 组播(multicast) | 首字节的最低有效位 = 1 | 01-00-5E-00-00-01 |
| 广播(broadcast) | 48 位全 1 | FF-FF-FF-FF-FF-FF |
适配器(网卡)收到一个帧时的判断次序:
text
① 目的地址是广播 FF-FF-FF-FF-FF-FF -> 收下, 交上层
② 目的地址与本机 MAC 完全相同 -> 收下, 交上层
③ 目的地址是组播地址且本机已加入该组 -> 收下, 交上层
④ 其余情况 -> 直接丢弃, 不交上层⚠️ 三条关于 MAC 地址的常见考点:
- MAC 地址不是"位置",而是"身份"——网卡换到哪台机器、哪个网络,MAC 都不变(不像 IP 地址会随接入网络变化)。 这一点是"平面地址 vs 层次地址"的最直观对照。
- 广播地址只有"全 1"这一种,与网络号无关——因为 MAC 是平面地址,没有"网络"这个概念。
- MAC 地址由 IEEE 统一分配 OUI,保证全球唯一——但"唯一"是"出厂时唯一",软件可以改(这也是"MAC 地址欺骗"的原理)。
三、以太网帧格式:Ethernet V2 的七个字段
帧格式(Ethernet V2 / DIX Ethernet,必背):
text
┌─────────┬──────┬───────────┬───────────┬────────┬───────────────┬─────────┐
│ 前导码 │ SFD │ 目的 MAC │ 源 MAC │ 类型 │ 数据 │ FCS │
│ 7 B │ 1 B │ 6 B │ 6 B │ 2 B │ 46 ~ 1500 B │ 4 B │
└─────────┴──────┴───────────┴───────────┴────────┴───────────────┴─────────┘
└── 物理层同步开销, 不计入帧长 ──┘└──────────── 帧长 = 64 ~ 1518 B ───────────┘
└── 首部 14 B ──┘ └ 尾部 4 B ┘| 字段 | 长度 | 作用 |
|---|---|---|
| 前导码(preamble) | 7 B | 10101010 重复 7 次,让接收方的时钟与发送方同步——不计入帧长 |
| SFD(帧开始定界符) | 1 B | 10101011,最后一个 11 表示"帧正式开始了"——不计入帧长 |
| 目的 MAC | 6 B | 接收方的物理地址 |
| 源 MAC | 6 B | 发送方的物理地址 |
| 类型(type) | 2 B | 上层协议:0x0800 = IP、0x0806 = ARP、0x86DD = IPv6(≥ 0x0600 = 1536 视为"类型",小于它则按 IEEE 802.3 当作"长度") |
| 数据 | 46 ~ 1500 B | 上层载荷;不足 46 B 必须填充(padding) |
| FCS | 4 B | CRC-32 校验码(见 net/21-error.md 与 net/20-framing.md) |
★ 合法性规则(必背):
| 约束 | 值 | 来历 |
|---|---|---|
| 帧长下限 | 64 B | net/23-csma.md) |
| 帧长上限 | 1518 B | MTU 1500 + 14 + 4 |
| 数据下限 | 46 B | 64 − 14 − 4 |
| 数据上限 | 1500 B | = MTU |
四种"无效帧"(收到就丢,不转发):
text
① 帧长 < 64 B —— 太短, 可能是一段"冲突碎片"(runt)
② 帧长 > 1518 B —— 超长帧 (giant), 可能是发送方故障
③ FCS 校验失败 —— 传输过程中出了位错
④ 数据长度不是整数个字节 —— 位丢失造成的帧结构错误⚠️ "为什么以太网要规定最小帧 64 B"这一条要连着物理意义一起记:因为"帧的发送时间必须 ≥ 争用期",否则"帧已经发完了,冲突信号还在路上"——发送方会误以为发送成功,而接收方收到的是一段被破坏的碎片。 所以"长度 < 64 B 的帧一律视为冲突碎片直接丢弃"——反过来,"收满 64 B 还没有检测到冲突"就说明"抢道成功"了。
"以太网帧效率"锚点(与 net/01-architecture.md 的 58 B 开销口径一致):
| 数据长度 | 帧长 | 帧效率 |
|---|---|---|
| 46 B(最小) | 64 B | 71.88% |
| 100 B | 118 B | 84.75% |
| 512 B | 530 B | 96.60% |
| 1024 B | 1042 B | 98.27% |
| 1500 B(最大) | 1518 B | 98.81% |
四、交换机:按 MAC 地址转发,自己学会地址表
交换机(switch)就是"多端口的网桥",工作在数据链路层,按 MAC 地址决定"从哪个端口转发出去"。
★ MAC 地址表(转发表)的自学习过程(本节核心):
text
交换机启动时转发表是空的。每收到一个帧, 就做两件事:
① 学习(记录源地址): 把"源 MAC + 收到该帧的端口号"写进转发表
—— 理由: 这个帧既然从端口 1 进来, 说明这个源地址就在端口 1 那一侧
② 转发(查目的地址):
转发表里有目的地址, 且与入端口不同 -> 只从该端口转发(单播)
转发表里有目的地址, 但就是入端口本身 -> 丢弃(它在同一侧, 不需要过交换机)
转发表里没有目的地址 -> 泛洪(flooding): 从除入端口外的所有端口发出去★ 自学习演算(锚点:4 台主机 A/B/C/D 接在交换机端口 1/2/3/4,依次发生 6 次通信):
| 次序 | 事件 | 学习动作 | 转发动作 |
|---|---|---|---|
| ① | A(端口 1)发给 B | 学习 A → 端口 1 | 表里没有 B → 泛洪(除端口 1 外全部) |
| ② | B(端口 2)发给 A | 学习 B → 端口 2 | 表里有 A → 只从端口 1 转发 |
| ③ | C(端口 3)发给 A | 学习 C → 端口 3 | 表里有 A → 只从端口 1 转发 |
| ④ | A(端口 1)发给 C | A 已在表中且一致 → 不更新 | 表里有 C → 只从端口 3 转发 |
| ⑤ | D(端口 4)发给 C | 学习 D → 端口 4 | 表里有 C → 只从端口 3 转发 |
| ⑥ | C(端口 3)发给 D | C 已在表中且一致 → 不更新 | 表里有 D → 只从端口 4 转发 |
最终转发表:A → 1、B → 2、C → 3、D → 4。
⚠️ 三个易错点:
- 只有第 ① 次是泛洪,之后都变成"定向转发"——这就是"自学习"的收益:交换机不需要人工配置,用着用着就全知道了。
- "源地址学习"与"目的地址转发"是两件独立的事——即使这个帧最后被丢弃(比如目的地址就在入端口一侧),源地址也已经学到了。
- 转发表条目会"老化"(默认 300 s)——因为主机可能换端口(插到别的口上),必须让旧条目过期,否则会转发到错的端口。
三种转发模式(时延差异是本节的量化锚点):
| 模式 | 什么时候开始转发 | 时延(100 Mbps,1518 B 帧) | 能过滤错帧吗 |
|---|---|---|---|
| 存储转发(store-and-forward) | 收完整个帧、校验通过后 | 121.44 μs(1518 B 全部收完) | 能 |
| 直通(cut-through) | 只读了目的 MAC(前 6 B)就转发 | 0.48 μs(6 B) | 不能(错帧也照转) |
| 无碎片(fragment-free) | 收满 64 B 后转发 | 5.12 μs(64 B) | 能过滤冲突碎片 |
⚠️ 121.44 μs 与 0.48 μs 相差 253 倍,这个对比最能说明"为什么直通交换机适合高性能场景":代价是"错帧也会被转发出去",把纠错的负担推给了终端——所以高端交换机通常"可在两种模式间配置"。
交换机与集线器的"带宽账":
| 设备 | 24 端口 / 1 Gbps 时 | 说明 |
|---|---|---|
| 集线器 | 所有端口共享 1 Gbps——24 台机器平均每人 41.67 Mbps | 物理层设备,同一时刻只能有一个端口发 |
| 交换机(半双工) | 每端口 1 Gbps,总容量 24 Gbps | 每个端口是一个独立冲突域 |
| 交换机(全双工) | 每端口同时收发 1 Gbps,总容量 48 Gbps | 全双工下无冲突,不需要 CSMA/CD |
⚠️ "全双工"是以太网历史上的分水岭:它让"共享信道"变成了"点对点专线",从根本上取消了冲突——今天机房里的以太网基本都是全双工,CSMA/CD 只在"半双工 + 共享介质"的历史场景里还写着。
生成树协议(STP):交换机之间若接成环,广播帧会无限循环(广播风暴)、转发表也会被搅乱——STP 通过"选举根桥 + 阻塞冗余端口"把有环拓扑逻辑上变成一棵树(物理上仍有备用链路,某条断了才启用)。
五、冲突域与广播域:三设备对照
| 设备 | 工作层 | 看得懂哪种地址 | 隔离冲突域 | 隔离广播域 |
|---|---|---|---|---|
| 集线器(hub) | 物理层 | 看不懂任何地址 | 不能 | 不能 |
| 网桥 / 交换机 | 数据链路层 | MAC 地址 | 能(每端口一个冲突域) | 不能(除非划 VLAN) |
| 路由器 | 网络层 | IP 地址 | 能 | 能 |
计数法(必背口诀):
text
冲突域: 交换机每个端口 = 1 个; 集线器整机 = 1 个(内部共享)
广播域: 路由器每个接口 = 1 个; 交换机/集线器不切分(除非 VLAN)★ 锚点例:1 台交换机,3 个端口各接 1 台集线器,每台集线器接 4 台主机。
text
冲突域 = 3 个 (每台集线器整机算 1 个; 交换机与集线器相连的 3 条链路各属于对应集线器的那个域)
广播域 = 1 个 (交换机和集线器都不切分广播域, 全网是一个)
主机数 = 12 台★ 再一个复合例:1 台路由器下挂 2 台交换机,每台交换机各接 2 台集线器,每台集线器接 3 台主机。
text
冲突域 = 2 台交换机 × 2 台集线器 = 4 个(集线器侧) + 1 个(两台交换机之间的链路) = 5 个
广播域 = 2 个 (路由器每个接口切出一个广播域: 左侧交换机一片, 右侧交换机一片)
主机数 = 2 × 2 × 3 = 12 台⚠️ "两台交换机之间的那条链路也算一个冲突域"是本题最容易漏的一处:因为那条链路两端都是交换机的端口,各自构成一个冲突域(只有"点到点全双工链路"在物理上不存在冲突,但按教材口径仍计入冲突域计数)。做题时以题目给定拓扑逐段数,别凭印象。
示例
例 1:C 实现——帧字段解析与帧长合法性检查
参数:三个帧的目的/源 MAC、类型(
0x0800IP /0x0806ARP /0x86DDIPv6)与数据长度;另用 7 个帧长做合法性判定。
#include <stdio.h>
/* 以太网帧长合法性: 不含前导码与 SFD, 必须在 64 ~ 1518 B */
int check_len(int len) {
if (len < 64) return -1; /* 太短: 可能是冲突碎片 */
if (len > 1518) return -2; /* 太长: 超长帧 */
return 0;
}
int main(void) {
const char *dst[3] = {"00-1A-2B-3C-4D-5E", "FF-FF-FF-FF-FF-FF", "01-00-5E-00-00-01"};
const char *src[3] = {"00-0C-29-11-22-33", "00-0C-29-11-22-33", "00-0C-29-11-22-33"};
int type[3] = {0x0800, 0x0806, 0x86DD}; /* IP / ARP / IPv6 */
const char *tn[3] = {"IP", "ARP", "IPv6"};
int data[3] = {1500, 46, 1000};
int lens[7] = {64, 46, 63, 1518, 1519, 2000, 512};
int i, len, r;
printf("① 以太网帧字段与帧长 (首部 14 B + 数据 + FCS 4 B)\n");
printf(" %-18s %-18s %-6s %-6s %-7s %-7s\n",
"DST MAC", "SRC MAC", "TYPE", "NET", "DATA", "FRAME");
for (i = 0; i < 3; i++) {
len = 14 + data[i] + 4;
printf(" %-18s %-18s %04X %-6s %4d B %4d B\n",
dst[i], src[i], type[i], tn[i], data[i], len);
}
printf(" 前导码 7 B + SFD 1 B 不计入帧长; 数据不足 46 B 要填充\n");
printf("\n② 帧长合法性检查\n");
for (i = 0; i < 7; i++) {
r = check_len(lens[i]);
printf(" 帧长 %4d B -> %s\n", lens[i],
r == 0 ? "合法"
: r == -1 ? "非法: 小于最小帧 64 B (冲突碎片)"
: "非法: 超过最大帧 1518 B (超长帧)");
}
printf("\n③ 三设备对两个域的隔离能力 (判据: 看得懂哪种地址)\n");
printf(" 集线器 物理层 : 隔离冲突域 不能 隔离广播域 不能\n");
printf(" 交换机 链路层 : 隔离冲突域 能 隔离广播域 不能\n");
printf(" 路由器 网络层 : 隔离冲突域 能 隔离广播域 能\n");
printf("\n④ 三种转发模式的时延 (100 Mbps, 1518 B 帧)\n");
printf(" 存储转发: 收完整帧 %.2f us 直通: 只看前 6 B %.2f us 无碎片: 收满 64 B %.2f us\n",
1518 * 8 / 100.0, 6 * 8 / 100.0, 64 * 8 / 100.0);
return 0;
}
c 本站为静态站,不提供在线运行;可复制到本地用 gcc / python 执行
预期输出:
① 以太网帧字段与帧长 (首部 14 B + 数据 + FCS 4 B)
DST MAC SRC MAC TYPE NET DATA FRAME
00-1A-2B-3C-4D-5E 00-0C-29-11-22-33 0800 IP 1500 B 1518 B
FF-FF-FF-FF-FF-FF 00-0C-29-11-22-33 0806 ARP 46 B 64 B
01-00-5E-00-00-01 00-0C-29-11-22-33 86DD IPv6 1000 B 1018 B
前导码 7 B + SFD 1 B 不计入帧长; 数据不足 46 B 要填充
② 帧长合法性检查
帧长 64 B -> 合法
帧长 46 B -> 非法: 小于最小帧 64 B (冲突碎片)
帧长 63 B -> 非法: 小于最小帧 64 B (冲突碎片)
帧长 1518 B -> 合法
帧长 1519 B -> 非法: 超过最大帧 1518 B (超长帧)
帧长 2000 B -> 非法: 超过最大帧 1518 B (超长帧)
帧长 512 B -> 合法
③ 三设备对两个域的隔离能力 (判据: 看得懂哪种地址)
集线器 物理层 : 隔离冲突域 不能 隔离广播域 不能
交换机 链路层 : 隔离冲突域 能 隔离广播域 不能
路由器 网络层 : 隔离冲突域 能 隔离广播域 能
④ 三种转发模式的时延 (100 Mbps, 1518 B 帧)
存储转发: 收完整帧 121.44 us 直通: 只看前 6 B 0.48 us 无碎片: 收满 64 B 5.12 us⚠️ 三点说明:
- 本机无 C 编译器:此段代码逐行人工审查,并用等价的 Python 实现实跑核对,输出 23 行逐字一致。
%04X把类型字段打成 4 位十六进制(0800)而不是0x800:以太网类型字段惯例写成 4 位十六进制、去掉0x前缀——%X会丢掉前导 0,必须用%04X。- 表头用 ASCII(
DST MAC/SRC MAC/TYPE/NET)而不是中文:C 的%-18s按字节补齐,一个汉字占 3 字节、显示却只有 2 列——用中文做表头必然列错位(这与net/10-physical.md把编码名写成NRZ/Manchester是同一条纪律)。中文表头写在正文的表格里即可。 - 时延用的是"μs = 比特数 / 100"这个快捷算法:因为 100 Mbps 下 1 比特 = 0.01 μs——
, 。 换成 1 Gbps 就把除数改成 1000。
例 2:Python——帧结构、自学习、冲突域与转发时延
def pad(s, w):
"""按"显示宽度"补空格: 中文算 2 列, 否则终端里对不齐"""
return s + ' ' * max(0, w - sum(2 if ord(c) > 0x2000 else 1 for c in s))
print('=== ① 以太网演进与命名 (速率 + BASE + 介质) ===')
print(' ' + pad('标准', 14) + pad('速率', 10) + pad('编码', 22) + pad('网段', 10) + '要点')
for nm, rate, code, seg, note in [('10BASE-5', '10M', '曼彻斯特', '500 m', '粗同轴总线'),
('10BASE-2', '10M', '曼彻斯特', '185 m', '细同轴总线'),
('10BASE-T', '10M', '曼彻斯特(20 MHz)', '100 m', '双绞线 + 集线器'),
('100BASE-TX', '100M', '4B/5B', '100 m', '快速以太网'),
('1000BASE-T', '1G', '8B/10B 类', '100 m', '千兆, 全双工为主'),
('10GBASE-T', '10G', '复杂编码', '100 m', '万兆, 不用 CSMA/CD')]:
print(' ' + pad(nm, 14) + pad(rate, 10) + pad(code, 22) + pad(seg, 10) + note)
print()
print('=== ② MAC 地址: 48 位 = 24 位 OUI + 24 位厂商号 ===')
print(' ' + pad('类型', 10) + pad('判别方法', 34) + '例子')
for t, how, ex in [('单播', '首字节最低有效位 = 0', '00-1A-2B-3C-4D-5E'),
('组播', '首字节最低有效位 = 1', '01-00-5E-00-00-01'),
('广播', '48 位全 1', 'FF-FF-FF-FF-FF-FF')]:
print(' ' + pad(t, 10) + pad(how, 34) + ex)
def kind(mac):
b = int(mac.split('-')[0], 16)
if mac.replace('-', '').upper() == 'FFFFFFFFFFFF':
return '广播'
return '组播' if b & 1 else '单播'
for m in ['00-1A-2B-3C-4D-5E', '01-00-5E-00-00-01', 'FF-FF-FF-FF-FF-FF', '03-00-5E-00-00-01']:
print(' 实测 %s -> %s' % (m, kind(m)))
print(' ★ MAC 是"平面地址": 换网络不变, 与位置无关(对比 IP 是层次地址)')
print()
print('=== ③ 帧格式与帧长 ===')
print(' 前导码 7 B + SFD 1 B (不计入帧长) | 目的 6 + 源 6 + 类型 2 | 数据 46~1500 | FCS 4')
print(' ' + pad('数据长度', 12) + pad('帧长', 10) + pad('开销占比', 12) + '帧效率')
for n in [46, 100, 512, 1024, 1500]:
print(' ' + pad('%d B' % n, 12) + pad('%d B' % (n + 18), 10)
+ pad('%.2f%%' % (18 * 100.0 / (n + 18)), 12) + '%.2f%%' % (n * 100.0 / (n + 18)))
print(' 类型字段: 0800 = IP, 0806 = ARP, 86DD = IPv6; >= 0600 视为"类型"')
print()
print('=== ④ 四种无效帧 ===')
for a, b in [('帧长 < 64 B', '太短, 可能是冲突碎片 (runt)'), ('帧长 > 1518 B', '超长帧 (giant)'),
('FCS 校验失败', '传输中出现位错'), ('数据非整数字节', '位丢失造成的结构错误')]:
print(' ' + pad(a, 20) + b)
print(' ★ 收到无效帧一律"直接丢弃、不通知发送方" —— 可靠性交给 TCP')
print()
print('=== ⑤ 交换机 MAC 地址表自学习 (A/B/C/D 接端口 1/2/3/4) ===')
seq = [('A', 'B', 1), ('B', 'A', 2), ('C', 'A', 3), ('A', 'C', 1),
('D', 'C', 4), ('C', 'D', 3)]
tbl = {}
for i, (s, d, p) in enumerate(seq, 1):
if s in tbl:
learn = '源 %s 已在表中(端口 %d), %s' % (s, tbl[s], '一致' if tbl[s] == p else '更新')
else:
learn = '学习 %s -> 端口 %d' % (s, p)
tbl[s] = p
if d in tbl and tbl[d] != p:
fwd = '只从端口 %d 转发' % tbl[d]
elif d in tbl:
fwd = '丢弃(目的与源同侧)'
else:
fwd = '泛洪(除端口 %d 外全部)' % p
print(' %d. %s(端口 %d) 发给 %s: %s; %s' % (i, s, p, d, learn, fwd))
print(' 最终转发表: ' + ', '.join('%s -> 端口 %d' % (k, tbl[k]) for k in sorted(tbl)))
print(' ★ 只有第 1 次泛洪, 之后都定向转发; 条目老化时间默认 300 s')
print()
print('=== ⑥ 三种转发模式 (100 Mbps, 1518 B 帧) ===')
print(' ' + pad('模式', 20) + pad('何时开始转发', 26) + pad('时延', 14) + '能否过滤错帧')
for nm, when, bits, ok in [('存储转发', '收完整个帧并校验', 1518 * 8, '能'),
('直通', '只读了目的 MAC(前 6 B)', 6 * 8, '不能'),
('无碎片', '收满 64 B', 64 * 8, '能(过滤冲突碎片)')]:
print(' ' + pad(nm, 20) + pad(when, 26) + pad('%.2f us' % (bits / 100.0), 14) + ok)
print(' ★ 直通比存储转发快约 253 倍(121.44 / 0.48) —— 代价是错帧也照转')
print()
print('=== ⑦ 冲突域 / 广播域 ===')
print(' ' + pad('设备', 12) + pad('工作层', 14) + pad('隔离冲突域', 16) + '隔离广播域')
for a, b, c, d in [('集线器', '物理层', '不能', '不能'),
('交换机', '数据链路层', '能(每端口一个)', '不能(除非 VLAN)'),
('路由器', '网络层', '能', '能')]:
print(' ' + pad(a, 12) + pad(b, 14) + pad(c, 16) + d)
print()
print(' 例 1: 1 台交换机 + 3 个端口各接 1 台集线器 + 每台集线器 4 台主机')
print(' 冲突域 = 3 (集线器整机算 1 个); 广播域 = 1; 主机 12 台')
print(' 例 2: 1 台路由器 + 2 台交换机 + 每台交换机接 2 台集线器 + 每台集线器 3 台主机')
cf = 2 * 2 + 1
print(' 冲突域 = %d (4 个集线器侧 + 1 条交换机间链路); 广播域 = 2 (路由器切分); 主机 12 台'
% cf)
print()
print('=== ⑧ 交换机的带宽账 ===')
print(' ' + pad('配置', 26) + pad('每端口', 18) + pad('总容量', 16) + '说明')
for a, b, c, d in [('集线器 24 口 1 Gbps', '平均 41.67 Mbps', '共享 1 Gbps', '物理层: 同一时刻只有一个口能发'),
('交换机 24 口半双工', '1 Gbps', '24 Gbps', '每端口一个冲突域'),
('交换机 24 口全双工', '收发各 1 Gbps', '48 Gbps', '无冲突, 不需要 CSMA/CD')]:
print(' ' + pad(a, 26) + pad(b, 18) + pad(c, 16) + d)
print(' ★ 全双工是分水岭: "共享信道"变成"点到点专线", 冲突从根本上消失')
python 本站为静态站,不提供在线运行;可复制到本地用 gcc / python 执行
输出对照(真实运行结果):
=== ① 以太网演进与命名 (速率 + BASE + 介质) ===
标准 速率 编码 网段 要点
10BASE-5 10M 曼彻斯特 500 m 粗同轴总线
10BASE-2 10M 曼彻斯特 185 m 细同轴总线
10BASE-T 10M 曼彻斯特(20 MHz) 100 m 双绞线 + 集线器
100BASE-TX 100M 4B/5B 100 m 快速以太网
1000BASE-T 1G 8B/10B 类 100 m 千兆, 全双工为主
10GBASE-T 10G 复杂编码 100 m 万兆, 不用 CSMA/CD
=== ② MAC 地址: 48 位 = 24 位 OUI + 24 位厂商号 ===
类型 判别方法 例子
单播 首字节最低有效位 = 0 00-1A-2B-3C-4D-5E
组播 首字节最低有效位 = 1 01-00-5E-00-00-01
广播 48 位全 1 FF-FF-FF-FF-FF-FF
实测 00-1A-2B-3C-4D-5E -> 单播
实测 01-00-5E-00-00-01 -> 组播
实测 FF-FF-FF-FF-FF-FF -> 广播
实测 03-00-5E-00-00-01 -> 组播
★ MAC 是"平面地址": 换网络不变, 与位置无关(对比 IP 是层次地址)
=== ③ 帧格式与帧长 ===
前导码 7 B + SFD 1 B (不计入帧长) | 目的 6 + 源 6 + 类型 2 | 数据 46~1500 | FCS 4
数据长度 帧长 开销占比 帧效率
46 B 64 B 28.12% 71.88%
100 B 118 B 15.25% 84.75%
512 B 530 B 3.40% 96.60%
1024 B 1042 B 1.73% 98.27%
1500 B 1518 B 1.19% 98.81%
类型字段: 0800 = IP, 0806 = ARP, 86DD = IPv6; >= 0600 视为"类型"
=== ④ 四种无效帧 ===
帧长 < 64 B 太短, 可能是冲突碎片 (runt)
帧长 > 1518 B 超长帧 (giant)
FCS 校验失败 传输中出现位错
数据非整数字节 位丢失造成的结构错误
★ 收到无效帧一律"直接丢弃、不通知发送方" —— 可靠性交给 TCP
=== ⑤ 交换机 MAC 地址表自学习 (A/B/C/D 接端口 1/2/3/4) ===
1. A(端口 1) 发给 B: 学习 A -> 端口 1; 泛洪(除端口 1 外全部)
2. B(端口 2) 发给 A: 学习 B -> 端口 2; 只从端口 1 转发
3. C(端口 3) 发给 A: 学习 C -> 端口 3; 只从端口 1 转发
4. A(端口 1) 发给 C: 源 A 已在表中(端口 1), 一致; 只从端口 3 转发
5. D(端口 4) 发给 C: 学习 D -> 端口 4; 只从端口 3 转发
6. C(端口 3) 发给 D: 源 C 已在表中(端口 3), 一致; 只从端口 4 转发
最终转发表: A -> 端口 1, B -> 端口 2, C -> 端口 3, D -> 端口 4
★ 只有第 1 次泛洪, 之后都定向转发; 条目老化时间默认 300 s
=== ⑥ 三种转发模式 (100 Mbps, 1518 B 帧) ===
模式 何时开始转发 时延 能否过滤错帧
存储转发 收完整个帧并校验 121.44 us 能
直通 只读了目的 MAC(前 6 B) 0.48 us 不能
无碎片 收满 64 B 5.12 us 能(过滤冲突碎片)
★ 直通比存储转发快约 253 倍(121.44 / 0.48) —— 代价是错帧也照转
=== ⑦ 冲突域 / 广播域 ===
设备 工作层 隔离冲突域 隔离广播域
集线器 物理层 不能 不能
交换机 数据链路层 能(每端口一个) 不能(除非 VLAN)
路由器 网络层 能 能
例 1: 1 台交换机 + 3 个端口各接 1 台集线器 + 每台集线器 4 台主机
冲突域 = 3 (集线器整机算 1 个); 广播域 = 1; 主机 12 台
例 2: 1 台路由器 + 2 台交换机 + 每台交换机接 2 台集线器 + 每台集线器 3 台主机
冲突域 = 5 (4 个集线器侧 + 1 条交换机间链路); 广播域 = 2 (路由器切分); 主机 12 台
=== ⑧ 交换机的带宽账 ===
配置 每端口 总容量 说明
集线器 24 口 1 Gbps 平均 41.67 Mbps 共享 1 Gbps 物理层: 同一时刻只有一个口能发
交换机 24 口半双工 1 Gbps 24 Gbps 每端口一个冲突域
交换机 24 口全双工 收发各 1 Gbps 48 Gbps 无冲突, 不需要 CSMA/CD
★ 全双工是分水岭: "共享信道"变成"点到点专线", 冲突从根本上消失八条结论:
- 以太网的命名是"速率 + 基带 + 介质":
10BASE-T→ 10 Mbps、基带、双绞线——看名字就能读出关键参数。 - 演进的三级跳:共享总线(同轴)→ 共享星型(集线器)→ 独享星型(交换机)——只有到了交换机 + 全双工,"冲突"才从根本上消失。
- ★ MAC 地址判型:首字节最低有效位 0 = 单播、1 = 组播、48 位全 1 = 广播;实测
03-00-5E-...这类"最低位为 1"的地址是组播,不是单播。 - MAC 是平面地址、IP 是层次地址:MAC 只标识"身份",不标识"位置"——所以换网络要换 IP,不用换 MAC。
- 帧长锚点:数据 46 ~ 1500 B、帧长 64 ~ 1518 B、固定开销 18 B;效率 46 B → 71.88%、1500 B → 98.81%。
- ★ 自学习演算:首帧泛洪(表里没目的地址),之后全部定向转发;"学源、查目的"是两件独立的事;条目 300 s 老化。
- ★ 转发模式时延锚点:存储转发 121.44 μs、直通 0.48 μs、无碎片 5.12 μs(100 Mbps、1518 B)——直通快 253 倍,代价是不能过滤错帧。
- ★ 冲突域/广播域锚点:例 1(1 交换机 + 3 集线器)→ 冲突域 3、广播域 1;例 2(1 路由器 + 2 交换机 + 4 集线器)→ 冲突域 5、广播域 2——"交换机间的那条链路也算 1 个冲突域"是最易漏的一处。
考点
考点
1. 必背结论
- 以太网 = IEEE 802.3;无连接、不可靠(坏帧直接丢、不通知、不重传,可靠性交给 TCP)。
- 命名规则:速率 + BASE(基带)+ 介质;10BASE-T = 10 Mbps 基带双绞线。
- 演进三级跳:共享总线(同轴)→ 共享星型(集线器)→ 独享星型(交换机 + 全双工)。
- 编码与速率对应:10BASE-T 用曼彻斯特(需 20 MHz);100BASE-TX 用 4B/5B(125 MBaud)。
- ★ MAC 地址 48 位:前 24 位 OUI(IEEE 分配)+ 后 24 位(厂商分配)。
- ★ MAC 地址三类判别:首字节最低有效位 = 0 单播、= 1 组播;48 位全 1(
FF-FF-FF-FF-FF-FF)广播。 - 网卡收帧判断次序:广播 → 收;与本机 MAC 相同 → 收;组播且已加入该组 → 收;其余丢弃。
- MAC 是平面地址(换网络不变),IP 是层次地址(换网络要变)。
- ★ 帧格式(Ethernet V2):前导码 7 B + SFD 1 B(不计入帧长)+ 目的 MAC 6 + 源 MAC 6 + 类型 2 + 数据 46~1500 + FCS 4。
- ★ 帧长:64 ~ 1518 B;首部 14 B + FCS 4 B = 固定开销 18 B;数据 46 ~ 1500 B。
- 类型字段:
0x0800= IP、0x0806= ARP、0x86DD= IPv6;≥0x0600(1536)视为"类型",否则按 802.3 当"长度"。 - ★ 四种无效帧:帧长 < 64 B(冲突碎片)/ > 1518 B(超长帧)/ FCS 错 / 数据非整数字节——一律丢弃。
- 帧效率锚点:46 B → 64 B(71.88%);1500 B → 1518 B(98.81%)。
- ★ 交换机自学习:收到帧 → 学"源 MAC + 入端口";查"目的 MAC" → 有则定向转发、无则泛洪、与入端口相同则丢弃。
- 转发表条目老化 300 s;只有"目的地址未知"时才泛洪。
- ★ 三种转发模式的时延(100 Mbps、1518 B):存储转发 121.44 μs / 直通 0.48 μs / 无碎片 5.12 μs。
- 存储转发:收完整帧并校验才转发,能过滤错帧;直通:只读目的 MAC 就转发,最快但不能过滤错帧。
- STP(生成树协议):消除环路,防止广播风暴。
- ★ 三设备对照:集线器(物理层,都不隔离)/ 交换机(链路层,隔离冲突域,不隔离广播域)/ 路由器(网络层,两者都隔离)。
- ★ 计数口诀:冲突域——交换机每端口 1 个、集线器整机 1 个;广播域——路由器每接口 1 个。
- ★ 计数锚点:1 交换机 + 3 集线器 + 12 主机 → 冲突域 3、广播域 1;1 路由器 + 2 交换机 + 4 集线器 + 12 主机 → 冲突域 5、广播域 2。
- 带宽账:集线器共享(24 口 1 Gbps → 人均 41.67 Mbps);交换机全双工独享(24 口 → 总容量 48 Gbps)。
2. 高频陷阱
- 把前导码 7 B 与 SFD 1 B 算进帧长:错。它们是物理层同步开销——算进去会得出"最小帧 72 B"。
- 认为"MAC 地址首字节最高位决定单播/组播":错。是"最低有效位"(第 1 个字节的 bit 0)——看
01-00-5E-...的第一个字节0x01,最低位是 1,所以是组播。 - 把 MAC 地址当成"可路由的地址":错。MAC 是平面地址、不能用于跨网路由;跨网要靠 IP(路由器按 IP 转发,MAC 只在本网段内有效)。
- 认为"广播地址随子网变化":错。以太网广播恒为
FF-FF-FF-FF-FF-FF——它没有"网络号"的概念。 - 认为"交换机隔离广播域":错。交换机只隔离冲突域;要隔离广播域得用路由器或 VLAN。
- 认为"集线器每个端口是一个冲突域":错。集线器整机(所有端口)同属一个冲突域。
- 数冲突域时漏掉"交换机之间的链路":错。两台交换机之间的那条链路也是 1 个冲突域(教材口径按链路段计)。
- 认为"帧长 64 B 是数据部分的长度":错。64 B 是整个帧长,数据部分最小是 46 B。
- 把"直通转发"当默认模式:错。交换机默认是存储转发(能校验 FCS,可靠性高);直通是高性能场景的可选配置。
- 认为"以太网收到坏帧会要求重传":错。以太网直接丢帧、不通知——"可靠性"是 TCP 的事。
- 把"类型字段"答成"长度字段":要分清——Ethernet V2 的该字段是"类型"(≥ 0x0600);IEEE 802.3 的同一字段是"长度"(≤ 1500)。
- 认为"全双工也跑 CSMA/CD":错。全双工是点到点专线、没有冲突,不需要 CSMA/CD;CSMA/CD 只在半双工共享介质的场景下用。
- 认为"交换机没有环路问题":错。交换机接成环同样会有广播风暴和转发表震荡——所以要 STP。
3. 解题模板("以太网与交换机")
① 帧格式题: 数长度
前导码 7 + SFD 1 (都不计入帧长)
目的 6 + 源 6 + 类型 2 + 数据 46~1500 + FCS 4
帧长 = 14 + 数据 + 4 = 64 ~ 1518 B
② 帧长合法性: < 64 B 是冲突碎片; > 1518 B 是超长帧; 都要丢
③ MAC 判型: 看第一个字节的最低位 -> 0 单播, 1 组播; 全 1 = 广播
④ 自学习题: 逐帧两问 —— "学源地址(入端口)" + "查目的地址"
表里没有目的 -> 泛洪; 有且与入端口不同 -> 定向转发; 同端口 -> 丢弃
⑤ 冲突域/广播域: 逐段数
集线器整机 = 1 个冲突域; 交换机每端口 = 1 个; 交换机间链路 = 1 个
路由器每接口切出 1 个广播域
⑥ 转发时延: 时延 = 需要读完的比特数 / 数据率
存储转发 = 整帧; 直通 = 6 B; 无碎片 = 64 B
100 Mbps 下 1 bit = 0.01 us -> 1518 B 是 121.44 us
⑦ 带宽题: 集线器共享 / 交换机半双工独享 / 全双工双向4. 与相邻章节的接口
net/23-csma.md(介质访问控制):"最小帧 64 B = 争用期 × 数据率"整条推导在上一章;本章的"帧长合法性"就是那条结论的直接应用;"集线器不能隔离冲突域"也是上一章的结论。net/20-framing.md(封装成帧):上一章给出"帧 = 首部 + 数据 + 尾部"的通用结构,本章给出以太网的具体七字段;"以太网数据部分不做填充(完全透明)"的理由在上一章已经讲明。net/21-error.md(差错控制):帧尾 4 B FCS = CRC-32;"CRC 只能检错"在本章表现为"校验不过就丢帧、不重传"。net/30-ip.md(IP 数据报):"MTU 1500 = IP 层载荷上限"是两章的共用锚点——IP 分片就是把超过 1500 B 的载荷切开;下一章会算 4000 B 数据报的 3 片分法。net/01-architecture.md(体系结构):"交换机认 MAC、路由器认 IP"的设备归属判据就在本章的冲突域/广播域一节;两章的 58 B 封装开销口径完全一致。net/10-physical.md(物理层):"10BASE-T 的曼彻斯特需要 20 MHz"解释了"为什么百兆要换 4B/5B"——编码方式的选择是被介质带宽逼出来的。os/32-io.md(I/O 管理)与arch/40-bus.md(总线):"交换机按地址定向转发"与"总线按地址选通设备"是同一类结构——都是"用地址信息把数据送到正确的端口"。
小结
- 以太网 = IEEE 802.3,无连接、不可靠(坏帧直接丢,可靠性交给 TCP)。
- 命名:速率 + BASE + 介质;演进三级跳:共享总线 → 集线器星型 → 交换机全双工。
- ★ MAC 地址 48 位=24 位 OUI + 24 位厂商号;首字节最低位 0 单播 / 1 组播 / 48 位全 1 广播;MAC 是平面地址。
- ★ 帧格式:前导码 7 + SFD 1(不计入)+ 目的 6 + 源 6 + 类型 2 + 数据 46~1500 + FCS 4。
- ★ 帧长 64 ~ 1518 B(开销 18 B);效率 46 B → 71.88%、1500 B → 98.81%;四种无效帧一律丢弃。
- ★ 交换机自学习:学源地址(入端口)、查目的地址(有则定向、无则泛洪、同端口则丢弃);条目老化 300 s。
- ★ 转发模式时延(100 Mbps、1518 B):存储转发 121.44 μs / 直通 0.48 μs / 无碎片 5.12 μs。
- ★ 冲突域/广播域:集线器都不隔离;交换机隔离冲突域;路由器两者都隔离;锚点:3 集线器 + 1 交换机 → 冲突域 3、广播域 1。
- 带宽账:集线器共享(24 口 1 Gbps → 人均 41.67 Mbps);交换机全双工 48 Gbps。
下一篇:IP 数据报与 IPv4 地址
评论(0)
当前浏览器不允许本地存储,评论无法保存。
还没有评论,来说两句。