一、局域网通信的三种标准
局域网(LAN)的通信标准,历史上留下来并被实际使用的常见有三种:
| 标准 | 一句话 | 现状 |
|---|---|---|
| 以太网(Ethernet) | 基于碰撞检测 + 碰撞避免 | ★ 最常见,90% 的局域网是以太网,原理也最复杂 |
| 无线 LAN(Wireless LAN) | 原理与以太网相同,只是用无线技术承载 | 手机连上家里的路由器就是它 |
| 令牌环网(Token Ring) | 持有令牌者才能发言 | 现实中很少见,但原理一句话就懂 |
💡 一个实用的判断顺序:先把以太网彻底搞懂,另外两种是它的变体。
- 无线 LAN = 以太网换了个物理介质(无线电代替网线),碰撞检测与避免的逻辑一致
- 令牌环网 = 把「先干再说,冲突了重发」改成了「先拿令牌,拿到才发」
二、★ MAC 地址:网卡的身份证
局域网里每台主机都要有唯一的标识 ,否则无法判定「这条消息是不是发给本机的」。这个标识就是 MAC 地址。

2.1 硬指标
| 属性 | 值 |
|---|---|
| 长度 | 48 比特 = 6 个字节 |
| 表示 | 6 组十六进制数,中间用冒号隔开(如 00:16:3e:1a:2b:3c) |
| 存放位置 | 网卡内部专门的一段存储区域,出厂时写死 |
| 能否修改 | 硬件上不能改;但操作系统 / 虚拟机可以虚拟出一个 MAC |
| 唯一性 | 全球范围内通常唯一;但真正需要的只是在同一个子网内唯一 |
| 所属层 | 数据链路层 |
2.2 怎么看
bash
# Linux
$ ifconfig
eth0: flags=... mtu 1500
ether 00:16:3e:1a:2b:3c # ← ether 后面就是 MAC
eth0 里的 eth 就是 ether(以太) 的缩写。
powershell
# Windows
> ipconfig /all
以太网适配器 以太网:
物理地址. . . . . . . . . . . . . : 00-16-3E-1A-2B-3C # ← 物理地址 = MAC
✔ 两种系统显示的分隔符不同(Linux 用冒号,Windows 用连字符),这只是显示方式的问题,值是一样的。
2.3 三个容易忽略的点
① 很多硬件都有唯一标识,但 MAC 特殊在「要参与通信」
内存、磁盘也都有唯一标识(磁盘上的叫序列号 ),但那些标识只用于资产管理,不参与数据传输。网卡的 MAC 地址是要被写进帧里、参与寻址的,所以它是协议的一部分。
② 虚拟机里的 MAC 是「虚拟」出来的
在一台 Windows 上装了 Linux 虚拟机,两个系统看到的 MAC 可能不一样 ------ 因为虚拟机的网卡本身就是软件模拟出来的。这不影响通信,因为它只需要在这个虚拟网络里唯一。
③ MAC 由网卡驱动读上来
网卡里本来就有这个值,不加载操作系统它也在 。操作系统是通过网卡驱动程序把它读进内存的。
三、"以太网"这个名字,是在内涵物理学家
这个名字取得很随意,但背后的故事值得记 ------ 它同时解释了「ether」这个词和计算机工程师的幽默感。
3.1 物理学那一边
19 世纪末的物理共识:
声音传播需要介质
声带振动 → 空气振动 → 耳膜振动 → 听到声音
真空里面对面喊,听不见
↓ 于是一个自然的推论
光的传播,是不是也需要介质?
↓ 继续推
太阳到地球,光要跑 8 分钟
可宇宙是真空的
那宇宙里一定充满了一种看不见的介质
↓ 给它起个名字
★「以太」(Ether)
当时的物理学家还在激烈争论光的本质(波动说、粒子说,后来才有波粒二象性),「以太」就是为了解释光如何传播而提出的假说。
3.2 然后它被证伪了
后来的实验(迈克耳逊-莫雷实验)反复验证,宇宙中根本不存在「以太」这种物质。
于是,「以太」在物理学界成了一个笑话------被实验证明不存在的东西,就是不存在。
3.3 计算机这边接过了这个词
几十年后,计算机工程师在实验室里搞出了一种局域网通信标准,能让两台主机互相通信了。起名字的时候:
★ 这个名字的含义是:物理学界没能证实的东西,计算机领域实实在在做出来了。
于是这种局域网标准就叫做 以太网(Ethernet)。
✔ 这不是技术内容,但记住它有两个好处:一是 eth0 的 eth 从此有了含义;二是它很典型地说明了计算机领域的命名经常带着工程师的玩笑。
四、★ 以太网通信原理:一间教室里的那堂课
这是整讲最核心的一个比喻,一定要吃透。
4.1 场景
一间教室里,一个人站在讲台前,下面坐着张三、李四、王五、赵六。
讲台:"张三,你站起来,你的作业为什么没做?"
李四、王五、赵六 → 听到了吗? 听到了
→ 站起来了吗? 没有
→ 为什么?
因为提取了这句话的信息,发现叫的不是自己
★ 于是自动把这个消息丢弃了
张三 → 听到了吗? 听到了
→ 站起来了吗? 站起来了
→ 为什么?
因为这句话里明确叫了「张三」
反向也一样:
张三:"大哥,我作业早做了,是你自己没看。"
李四、王五、赵六 → 也都听到了
→ 但会处理这句话吗? 绝对不会
→ (现实中不可能李四跳出来说"你怎么能这么跟大哥说话")
→ ★ 因为这句话指的是「大哥」,不是自己
4.2 由此得到的结论
局域网通信的本质:消息发出去,所有人都能收到;只有目标主机会受理,其余主机全部丢弃。
| 现象 | 本质 |
|---|---|
| A 认为自己在和 C 「一对一通信」 | 只是逻辑上的一对一 |
| 实际上 | 周围有一大批主机都收到了这帧,只是都丢弃了 |
| 每台主机都要有唯一名字 | 否则无法判定「叫的是不是本机」 |
✔ 这个「逻辑上一对一、物理上一对多」的反差,是理解后面所有内容(抓包、广播、碰撞)的前提。
4.3 报文长什么样
于是主机 A 要发给主机 E 的消息,至少要有三部分:
┌──────────┬──────────┬────────────┐
│ 源 MAC │ 目的 MAC │ 消息主体 │
│ MacA │ MacE │ 「你好」 │
└──────────┴──────────┴────────────┘
用上一讲的结论来看,这又是一个结构体:
c
struct mac_frame {
unsigned char src[6]; // 源 MAC,6 字节
unsigned char dst[6]; // 目的 MAC,6 字节
char payload[]; // 消息主体
};
💡 注意这里 unsigned char src[6] ------ MAC 的 6 个字节正好对应一个长度为 6 的字符数组。报文的每一个字段,都能在结构体里找到对应。
五、泛洪 ≠ 广播:一字之差,性质完全不同
这是一个很容易被混用的概念,课堂专门做了区分。
| 概念 | 发生了什么 | 结果 |
|---|---|---|
| 泛洪 | 消息发到局域网上,所有主机都收到了 | 但非目标主机丢弃(不处理) |
| 广播 | 把目的 MAC 设为全 F (FF:FF:FF:FF:FF:FF) |
所有主机都受理 |
✔ 一句话区分:泛洪是"大家都能听见",广播是"大家都要处理"。
真正的广播要靠一个特殊地址来触发------目的 MAC 全 F 是一个约定好的特殊值,网卡看到这个值就知道「这帧是给所有人的,不能丢」。
六、抓包为什么能抓到别人的包
顺着第四节的结论往下推,会得到一个略带警示性的推论:
局域网中,所有主机都能收到所有帧
↓
★ 局域网里的数据是「透明」的、公开的
↓
所以抓包工具能抓到别人的包
↓
★ 这就是为什么需要加密
✔ 抓包工具的合法性,就建立在这个「所有人都能听见」的物理事实上。它不是破解了什么,而是本来就能听见。
💡 顺带解释了为什么早年很多协议(HTTP、Telnet、FTP)都不安全------它们假设了「只有通信双方能看到数据」,而这个假设在局域网里根本不成立。
七、★ 碰撞域:以太网本质上是一个临界资源
这一节会把网络课和系统课直接焊在一起。
7.1 从教室到网络
教室里能两个人同时说话吗?不能。
正在叫张三回答作业
↓
李四同时大声问王五"你那五毛钱什么时候还"
↓
两句话混在一起,谁也听不清
换成网络:
主机 A 正在往局域网上发消息(一串 0/1 的波形 / 高低电平)
↓
主机 B 同时也往局域网上发
↓
★ 两组光电信号在物理线路上叠加,互相干扰
↓
数据全废
7.2 结论
以太网中,任何一个时刻只允许一台主机向网络发送数据。
由此定义:
★ 一个以太网 = 一个碰撞域(Collision Domain)。
7.3 ★ 与操作系统的篇章相对应
把「任何时刻只允许一台主机使用以太网」这句话,和系统课的定义对齐:
| 系统课 | 网络课 |
|---|---|
| 临界资源 | 以太网 |
| 执行流(线程) | 一台台主机 |
| 互斥 | 任何时刻只允许一台主机发 |
| 加锁 | 碰撞检测 + 碰撞避免 |
✔ 结论:以太网本质上就是一个临界资源,所有主机就是一个个执行流,在竞争这份共享资源。
💡 但这里的「保护方式」和互斥锁有个关键差别,值得单独记:
| 互斥锁 | 以太网 | |
|---|---|---|
| 策略 | 先申请,拿到了再进 | 不管三七二十一先干了 |
| 冲突时 | 根本不会发生冲突 | 冲突了再说,然后重发 |
| 代价 | 每次都要付出申请开销 | 大概率一次就成功,省掉协调成本 |
✔ 换句话说:锁是悲观策略,以太网是乐观策略。 冲突概率低的时候,乐观策略的平均效率更高。
八、碰撞检测与碰撞避免
既然没有「锁」,那以太网怎么保证秩序?靠两步:先检测,再避免。
8.1 碰撞检测:自己发的消息自己也能收到
A 把数据发出去
↓
★ A 自己也能收到自己发的这帧(类比:说话时自己能听见自己的声音)
↓
收回来之后做校验(CRC 等)
↓
发现对不上 → 判定发生了碰撞
✔ 「自己能听见自己说话」这个事实,正是碰撞检测得以实现的前提------发送方不需要别人告诉它出事了,它自己就能发现。
8.2 碰撞避免:随机休眠,错开重发
一旦检测到碰撞:
A 检测到冲突 → 随机休眠一段时间(比如 0.1 ms)
B 也检测到冲突 → 随机休眠一段时间(比如 0.2 ms)
↓
两人休眠时长不同 → 时间被错开
↓
休眠期间,C、D、E 没人跟它们抢,可以正常竞争网络资源
↓
A 醒来重发 / B 醒来重发,此时冲突概率已经很低
★ 关键在**「随机」**二字:如果两台主机休眠同样长的时间,醒来后还会再撞一次,然后无限循环。
九、令牌环网:令牌就是一把锁
以太网是「先干再说」,令牌环网是另一种思路。
教室里放一个瓶子(令牌)
↓
规定:只有持有瓶子的人才能说话,其余所有人闭嘴
↓
讲台拿着瓶子 → 说完 → 把瓶子交给张三
↓
张三拿着瓶子 → 只有他能说话,其他人都不能
↓
说完 → 传给李四 → 依次下去
★ 一句话点破:这个「令牌」,本质上就是一把锁。
| 系统课 | 令牌环网 |
|---|---|
| 拿到锁 | 拿到令牌 |
| 持有锁期间,其他线程阻塞 | 持有令牌期间,其他主机闭嘴 |
| 释放锁 | 把令牌传给下一台主机 |
✔ 令牌环网现实中很少遇到,但它是理解「互斥思想在不同场景下的不同实现」的绝佳对照:以太网是无锁的乐观并发,令牌环网是严格的持锁访问。
十、★ 换个视角:两台主机通信,本质是两个协议栈在通信
从这一节开始,看问题的方式要升级。
10.1 不要再把主机看成一台机器
以前的视角: 应该升级成的视角:
主机 A ←───→ 主机 B 协议栈 A ←───→ 协议栈 B
┌────────┐ ┌────────┐
│ 应用层 │ │ 应用层 │
│ 传输层 │ │ 传输层 │
│ 网络层 │ │ 网络层 │
│ 链路层 │ │ 链路层 │
└────────┘ └────────┘
10.2 数据是谁发起的
绝大多数情况下,发起通信的是用户,也就是最上面那一层的应用。
于是完整路径是:

发送端:用户层发起
↓ 自顶向下贯穿协议栈(应用层 → 传输层 → 网络层 → 链路层)
网卡
↓
网络
↓
对端网卡(硬件先收到)
↓ 自顶向上交付(链路层 → 网络层 → 传输层 → 应用层)
接收端:到达对端应用层
✔ 由此得到一个重要认识:平时说的「数据链路层之间的通信」,指的只是双方链路层这一层的对话;真正的通信,是贯穿整个协议栈的。
⚠ 谈局域网时容易一叶障目:只盯着链路层那一小块,忘了上面还有三层。
十一、★ 为什么要封装:因为发数据的是用户,发得出去的是网卡
11.1 同层都要有协议
既然网络协议栈是分层的,那么每一层都要有自己的协议:
- 应用层和之间有应用层的协议
- 传输层和之间有传输层的协议
- 网络层、数据链路层同理
生活中的例子------打电话:
两个人打电话,接通后第一句都是"喂"
↓
没人教过,双方都会说
↓
★ 这是【应用层】的协议:互相确认「对端能听见本端说话了」
而两部电话之间,要互相发信号、建立连接、让对方响铃
↓
★ 这是【电话这一层】的协议
11.2 既然有协议,就得把协议信息带上
协议是结构体。要告诉对端「本端是谁、发给谁、数据有多长」,就必须把这些字段一起发出去。
于是:把本层的协议结构体,二进制拷贝到报文的最前面。
★ 拷贝在前面的这部分,就叫做「协议报头」。
的东西本身 | 有效载荷(payload) |
| 快递单 | 协议报头(header) |
| 盒子 + 快递单 + 商品 | 报文(报头 + 有效载荷) |
✔ 这个比喻还顺带解释了一个关键性质:报头上的字段必须写在固定位置(快递单上「收件人」写在固定的那一栏),否则对端解析不到------这一点在第六节讲抓包时还会再遇到。
十二、★ 封装的完整过程
12.1 逐层添加报头
应用层: 「你好」
↓ 添加应用层报头
┌──────────┬────────┐
│ 应用层报头 │ 你好 │
└──────────┴────────┘
↓ 向下交付到传输层
传输层: ┌──────────┬──────────┬────────┐
│ 传输层报头 │ 应用层报头 │ 你好 │
└──────────┴──────────┴────────┘
↑ 对传输层来说,后面整块都是「有效载荷」,
它完全不关心里面是什么
↓ 继续向下
网络层: ┌────┬────┬────┬────┐
│网络层│传输层│应用层│ │
│ 报头 │ 报头 │ 报头 │ 你好 │
└────┴────┴────┴────┘
↓ 继续向下
数据链路层:┌────┬────┬────┬────┬────┐
│链路层│网络层│传输层│应用层│ │
│ 报头 │ 报头 │ 报头 │ 报头 │ 你好 │
└────┴────┴────┴────┴────┘
↓
★ 这一整块才真正被网卡发到网络上

12.2 定义
★ 报文从协议栈自顶向下逐次交付、不断添加报头的过程,叫做「封装」。
| 概念 | 含义 |
|---|---|
| 封装 | 自顶向下,逐层添加本层报头 |
| 报头(header) | 本层的协议结构体,加在报文最前面 |
| 有效载荷(payload) | 上层交付下来的整块内容,本层不解释它 |
💡 注意「有效载荷」这个词是相对的:
- 对传输层来说,有效载荷 = 应用层报头 + 数据
- 对链路层来说,有效载荷 = 网络层报头 + 传输层报头 + 应用层报头 + 数据
每一层都把上层交下来的整块当成不透明的载荷,只在最前面加自己的那一段。
12.3 为什么要自顶向下
原因只有一句:想发数据的是用户(在最上层),能把数据发出去的是网卡(在最下层)。
用户在应用层敲下"发送"
↓
但网卡是硬件,操作系统是网卡的管理者
↓
★ 所以数据必须穿过操作系统,也就必须穿过整个协议栈
和系统课对齐:
printf("hello");
↓
printf 底层封装了系统调用 write()
↓
因为操作系统是显示器的管理者,用户不能绕过它
send(sockfd, buf, len, 0);
↓
同样是系统调用
↓
因为操作系统是网卡的管理者,用户不能绕过它
✔ 「网络是操作系统的一部分」这个上一讲的结论,在这里有了具体的落点:发一个网络数据,本质上就是几次系统调用。
12.4 报头里到底写了什么
以应用层为例,最简单的报头只需要一个字段:
c
struct app_header {
int len; // 标明后面的数据有多少字节
};
对端收到后,直接读报文最前面的 sizeof(int) 个字节,就知道后面还有多长------这就是「快递单上写明件数」的网络版本。
后续课程里会遇到的真实报头,也都是结构体:
| 报头 | 结构体 | 层次 |
|---|---|---|
| IP 报头 | struct iphdr(含源 IP、目的 IP 等字段) |
网络层 |
| TCP 报头 | struct tcphdr(含端口号、标志位等) |
传输层 |
| UDP 报头 | struct udphdr |
传输层 |
✔ 无论哪一层,报头 = 结构体变量,这一点是上一讲「协议就是结构体」的直接延续。
12.5 一个类比:把对象写进文件再读出来
写 C 语言通讯录时,把 struct person 数组一个个写进文件,之后再按同样的结构体从文件里读回来,数据就恢复了。
同一个结构体 + 同样的读写顺序 → 数据可以原样还原
↓
★ 而 Linux 下,网络也是文件
↓
所以「往文件里写」和「往网络里写」在这件事上没有区别
✔ 这解释了封装为什么可行:双方用同一个结构体定义、按同样的顺序读写,那么前面那几个字节就一定会被解释成本层的报头字段。
十三、★ 解包与分用:每一层协议必备的两种能力
封装是自上而下加报头,那对端收到之后怎么办?反过来看。
13.1 解包:先把自己的报头摘下来
同层协议是互相认识的------对端的数据链路层收到整帧后,一定能提取出链路层报头,因为:
两边定义的是同一个结构体
↓
指针指向帧的头部,强转成对应的结构体类型
↓
★ 头部就拿到了
把本层的报头和有效载荷分离的过程,叫做「解包」。
13.2 分用:然后交给上层的哪一个协议
解包之后有个绕不开的问题:上层不止一个协议。
| 层 | 该层有哪些协议 |
|---|---|
| 传输层 | TCP、UDP |
| 网络层 | IP、ICMP、IGMP |
| 数据链路层(上层) | ARP、RARP |
那么链路层解包之后,有效载荷该交给网络层的哪一个?网络层解包之后,又该交给传输层的 TCP 还是 UDP?
★ 因此,任何一层协议(应用层除外)的报头里,必须提供两种能力:
| # | 必备能力 | 为什么 |
|---|---|---|
| ① | 能把报头和有效载荷分离 | 否则拆不开,也就无法向上交付 |
| ② | 能表明"有效载荷该交给上层的哪个协议" | 否则上层有多个协议,无从选择 |
辅导员的类比:
辅导员:"张三,你把这个文件袋去交给五号宿舍楼五楼的李四老师。"
↓
文件袋上必须写清楚交给谁
↓
★ 同理:每一层在报头里都要写入
"本层的有效载荷到对端后,应该交给上层的哪个协议"
★ 根据报头属性,决定把有效载荷交付给上层哪一个协议的过程,叫做「分用」。
13.3 完整流程
目标主机网卡收到帧
↓
链路层:解包(摘掉链路层报头)→ 分用(按报头交给网络层)
↓
网络层:解包(摘掉网络层报头)→ 分用(按报头交给传输层)
↓
传输层:解包 → 分用(交给应用层)
↓
应用层:拿到「你好」
✔ 于是从结果上看:同层之间在逻辑上直接拿到了对方同层要发的数据,这就是「同层之间直接通信」的真正含义。
13.4 ⚠ 一个容易漏掉的细节:不是发给本机的,在链路层就被丢了
链路层报头里写着 src MAC 和 dst MAC。
主机 B 收到一帧
↓
分析链路层报头,发现 dst MAC 是 MacC,不是自己
↓
★ 在链路层直接丢弃,不再向上交付
↓
上层完全感知不到这个报文曾经来过
✔ 所以站在上层的视角:只有发给自己的数据才会出现------它甚至不知道网上还有别的流量。
十四、★ 为什么叫"协议栈":封装是入栈,解包是出栈
14.1 把图换个画法就明白了
发送端 接收端
┌───────────┐
「你好」 │ 你好 │ ← 栈底
↓ 加应用层报头├───────────┤
│ 应用层报头 │
↓ 加传输层报头├───────────┤
│ 传输层报头 │
↓ 加网络层报头├───────────┤
│ 网络层报头 │
↓ 加链路层报头├───────────┤
│ 链路层报头 │ ← 栈顶(最外层)
└───────────┘
★ 教材画分层结构时,从来不解释这个过程叫什么。但把它画成栈,答案就摆在眼前:
入栈(封装):栈空 → 1 个 → 2 个 → 3 个 → 4 个 → 5 个
出栈(解包):5 个 → 4 个 → 3 个 → 2 个 → 1 个 → 空
这就是一个栈,所以它叫「协议栈」。
14.2 各层的数据叫什么(术语统一)
| 层 | 封装出来的整个东西叫什么 |
|---|---|
| 应用层 | 请求 / 应答 |
| 传输层 | ★ 数据段(segment) |
| 网络层 | ★ 数据报(datagram) |
| 数据链路层 | ★ 数据帧(frame) |
✔ 所以前面反复说的"局域网通信中主机 A 发给主机 E 的消息",准确的说法是------数据帧。
14.3 任何一层只认识自己的报头
类比快递员:只关心自己派发的快递,不关心快递里装的是什么。
报文 = 报头 + 有效载荷
这个公式对每一层都成立,只是"报头"和"有效载荷"的具体内容逐层不同。
十五、网卡的混杂模式:抓包的技术实现
第六节从"局域网数据透明"的角度解释过为什么能抓包。这里补上技术细节。
网卡和驱动程序默认只会把发送给本主机的报文向上交付------发现目的 MAC 不是自己,就在链路层丢弃(第 13.4 节)。
但网卡有一种模式,叫 混杂模式(Promiscuous Mode):
混杂模式下:
收到数据帧 → 不判断目的 MAC 是不是自己
→ 无脑向上交付
→ ★ 不管是不是发给本机的,全都交给上层
> ★ 抓包工具的原理,就是把自己的网卡设置成混杂模式。
✔ 这也说明:抓包不是"破解"了什么,只是让网卡不再帮忙过滤而已。 数据本来就在那里。
(顺带一句:这就是为什么局域网里跑明文协议很危险,加密是必需的。)
192.168.1.1
│ │ │ └─ 第 4 段
│ │ └──── 第 3 段
│ └─────── 第 2 段
└──────────── 第 1 段
* 每一段的取值范围是 **0--255**,**正好一个字节**
* **内核里用 4 个字节**表示;点分十进制是给人看的字符串形式
```bash
$ ifconfig
eth0: flags=... mtu 1500
inet 172.18.33.122 # ← inet 就是 IP 地址(网络地址)
ether 00:16:3e:1a:2b:3c # ← ether 是 MAC 地址
16.2 ★ IP 地址的作用
IP 地址用来在全球范围内标识主机的唯一性。
16.3 公网 IP 与内网 IP(提前铺一层)
⚠ 严格说,上面那句话指的是公网 IP 。真实世界里 IP 还分公网和内网(私有)两类,完整机制属于后面 NAT 与子网划分的内容。本讲先默认「IP = 公网 IP」。
不过成因可以先讲清楚:
IPv4 只有 32 位 → 最多表示 2^32 ≈ 42 亿台主机
↓
全球人口已超 80 亿,且车联网、IoT 让入网设备持续暴涨
↓
★ 地址远远不够
方案一:IPv6------彻底解决,但推不动
- 中国是世界上 IPv6 技术最强的国家之一;2008 年北京奥运会的场馆网络建设全部采用 IPv6
- 每个国家办奥运会时,都会把想向世界推广的技术拿出来展示(东京奥运会展示氢能源汽车,同理)
- 但推广极难,两个原因:
- 技术 :IP 协议在内核里。要让 IPv6 全球铺开,等于一夜之间把全世界所有操作系统升级一遍 ------ 做不到
- 政治:互联网脱胎于美国的阿帕网,核心技术由西方主导,不可能让某一国用新技术把整个互联网重构一遍
方案二:NAT(网络地址转换)------现实中的答案
- 把 IP 分成两块:公网 IP(不能重复) + 内网 IP(可以重复)
- 内网 IP 允许重复 → 变相增加了 IP 的绝对上限
- 访问外网时,运营商在出口处把内网 IP 换成公网 IP;返回时再做内网转发
✔ 这就解释了一个日常现象:在学校看到自己的 IP 是 192.168.x.x,回到宿舍看到的还是 192.168.x.x。 普通用户接触到的几乎全是内网 IP。
而买云服务器拿到的 IP 之所以能直接访问,是因为那是公网 IP。
💡 留下一个伏笔 :既然每台机器的 IP 都是独特的,为什么同一个局域网里所有主机的 IP 前半部分都一样?------这是子网划分与子网掩码要回答的问题,后续课程会讲。
十七、★ IP 与 MAC 到底有什么区别:跟着唐僧去取经
两套地址都号称"全球唯一",那到底为什么要两套?
17.1 先回答:哪个先有
网络的发展是从局部到整体的 ------ 先有局域网,后来才有广域网。
★ 所以 MAC 地址先有,IP 地址后有。 历史自己给出了答案。
17.2 西游记类比
唐僧带着四个"宠物"一路向西,每到一个地方,国王都会问同样的问题:
| 地点 | 国王问 | 唐僧答 | 国王补充 |
|---|---|---|---|
| 车迟国 | 和尚,你从哪儿来?到哪儿去? | 我从东土大唐 来,要去西天面见佛祖求取真经 | 那你下一站该去女儿国 |
| 女儿国 | 你从哪儿来、到哪儿去?上一站从哪儿来? | 从东土大唐来,去西天;上一站是车迟国 | 往西走,紧挨着的是黑风岭 |
| 黑风岭 | 和尚从哪来? | 出家人不打诳语,我从东土大唐来,我要去西天 | (然后就被抓走了) |
★ 于是唐僧身上有两套地址:
| 说法 | 对应到网络 | 性质 |
|---|---|---|
| 从哪儿来、到哪儿去 | 源 IP / 目的 IP | ★ 长远目标,全程不变 |
| 上一站从哪儿来、下一站去哪儿 | 源 MAC / 目的 MAC | ★ 当下目标,每站都变 |
生活里也一样:每个人身上都有两套地址------高三天天刷题是为了"考上大学"(长远目标),今天来听课是为了"学会这一节"(当下目标)。
17.3 ★ 核心结论
★ 目的 IP 的核心价值:提供路由的参考依据。
为什么唐僧在车迟国时,下一站必须去女儿国?因为他要去西天。 到了女儿国为什么必须去黑风岭?同样因为要去西天。
- 目的 IP 在整个转发过程中永远不变(唐僧在哪儿都说自己要去西天)
- 目的 MAC 每一站都不一样(下一站由当地情况决定)
✔ 一句话:IP 是长远目标,MAC 是当下目标。
17.4 各位国王,就是路由器
国王做的事是:听完唐僧的长远目标,再结合自己对本地路况的了解,告诉他下一站去哪。
------这正是路由器的工作。
17.5 ⚠ 修正一个常见误解
"MAC 地址全球唯一"这句话没错,但这不代表 MAC 在广域网里有效。
★ MAC 地址本质上是一种只在局域网内有效的地址。
下一节会看到它为什么每经过一个路由器就被换掉。
十八、★ 跨网段转发的完整过程
18.1 路由器是什么
| 属性 | 说明 |
|---|---|
| 作用 | 连接两个不同的子网 |
| 网卡 | 至少两张,左右各连一个子网 |
| IP | 每张网卡各配一个 IP,分别属于所连的子网 |
| 是不是主机 | ★ 路由器也是一台主机,只是主要职责是做路由 |
| 工作层次 | 网络层 + 数据链路层(教材常说"工作在网络层") |
💡 当代路由器已经不止工作在网络层,甚至支持到应用层 ------ 家里的路由器就有应用层(给路由器配账号密码时,数据就是发给路由器本身的)。但正常情况下路由器只用它的网络层功能;只有当报文真的是发给路由器自己时,才会向上交付到它自己的应用层。
18.2 场景(故意把两边设成不同的局域网技术)
主机 A 路由器 主机 B
192.168.2.2 ┌──────────┐ 172.168.2.2
MacA │ MacLeft │ MacRight MacB
│ │192.168.2.1│172.168.2.1 │
└── 以太网 ──── ┤ ├─ ── 令牌环网 ─────┘
(左子网) └──────────┘ (右子网)
同子网还有 192.168.2.3 / .4 / .5 ...
注意左边是以太网、右边是令牌环网 ------ 这是刻意设计的:底下两种完全不同的局域网技术,照样能通信。 这个设计在第 19 节会兑现。
18.3 ★ 第一步:主机 A 的判断
目的 IP = 172.168.2.2
本机 IP = 192.168.2.2(本子网是 192.168.2.x)
↓ 比对
172.168.2.2 与本子网所有主机都不一样
↓
★ 主机 A 并不知道 172.168.2.2 到底在哪儿(可能相隔千里)
但一定能确定:这个报文绝对不是发给本子网其他主机的
↓
★ 结论:交给路由器 ------ 因为只有路由器通向外面
唐僧类比:唐僧不知道西天具体在哪儿,但绝不可能一出门就往东走。 方向是能自己判断的。
💡 这里有个前提:**只要有网络层,就有路由功能。主机 A 同理,它知道自己的下一跳是谁。
⚠ 主机是如何拿到路由器 MAC 地址的?这是 ARP 的职责,属于后续内容。
18.4 第二步:封装(注意这里的错位)
网络层: SRC = 192.168.2.2(自己) DST = 172.168.2.2(★ 最终目标)
↓
数据链路层:SRC = MacA(自己) DST = MacLeft(★ 下一跳)
✔ IP 写的是最终目标,MAC 写的是下一跳。 这就是两套地址分工的具体体现,也是第 17 节那个结论的代码级落点。
18.5 第三步:泛洪,只有路由器收下
数据帧被扔到左子网上,所有主机都收到了:
目的 MAC = MacLeft
↓
192.168.2.3 / .4 / .5 ... 比对后发现不是自己 → 在链路层直接丢弃
↓
★ 只有路由器把这一帧收下了
18.6 第四步:解包 → 查路由 → 重新封装
① 链路层收到帧 → 解包,脱掉源/目的 MAC → 有效载荷交给网络层
② 网络层看到目的 IP = 172.168.2.2
③ 查路由:172.168.2.2 与右网卡(172.168.2.1)在同一子网 → 目标就在右侧
④ ★ 不能从网络层"直接横着传过去",必须重新向下交付
⑤ 重新封装链路层:SRC = MacRight(右网卡) DST = MacB(主机 B)
⑥ 从右网卡发出去(这里走的是令牌环网的驱动和帧格式)
✔ 关键动作就一句:向上交付时解过的包,向下交付时要重新封装。 路由器干的活就是"脱衣服、穿衣服"。
18.7 ★ 最终结论
★ 路由过程中,IP 地址不变,MAC 地址一直在变。
三台主机(发送方、路由器、目标主机)各自网络层收到的报文完全一样;而底层的 MAC 帧,每经过一个路由器就被整体替换一次。
💡 放大到任意跳数都成立:哪怕中间经过 100 个路由器,网络层往上看,报文从头到尾是同一份;MAC 报头则被不断地自动替换。

十九、★ 网络层的本质:给世界上所有网络提供一层虚拟化
顺着上一节往下想,会得到一个非常重要的认识。
19.1 底层是什么,已经不重要了
左子网是以太网,右子网是令牌环网,中间还可能有无线 LAN
↓
但到了网络层往上,所有报文长得完全一样
↓
★ 网络层往上,世界上就只有一种网络 ------ IP 网络
底层差异被谁消化掉了?数据链路层 + 各自的驱动程序。 是以太网就装以太网驱动、按以太网帧封装;是令牌环网就装令牌环驱动、按令牌环帧封装。而到了 IP 层,全部统一。
✔ 一个日常印证:在手机上(无线 LAN)发一条消息,和在有线的电脑上(以太网)发一条消息,对方收到的一模一样。 底层到底是无线 LAN 还是令牌环,已经不重要了。
19.2 这就是"加一层"的威力
★ 任何一个软件问题,都可以通过增加一层软件层来解决。
这句话在系统课已经见过一次:
| 场景 | 加的那一层 | 屏蔽了什么 |
|---|---|---|
| 一切皆文件 | struct file + f_op 函数指针 |
键盘、显示器、磁盘、网卡等硬件的差异 |
| ★ IP 网络 | 网络层(IP) | 以太网、令牌环网、无线 LAN 的差异 |
✔ IP 是一个伟大的发明,理由就在这里:它把异构的底层网络,抽象成了一个统一的网络。
19.3 这也解释了为什么 IP 必须写在内核里
网络层和驱动程序没有关系 ------它不关心底下是以太网还是令牌环。正因如此,它必须由每一个操作系统都实现一份;于是所有操作系统内部看到的网络,都是同一个 IP 网络。
(这一句正好呼应上一讲的结论:网络是操作系统的一部分。)
19.4 一个推论:想发明自己的局域网?随便
只要发明出来之后,把 IP 关连起来、配上对应的驱动,这套协议直接就能接入互联网。
------这正是为什么当年能有那么多种局域网标准并存(以太网、令牌环网、无线 LAN......),而上层的互联网却完全不受影响。

二十、★ 那只要 IP 行不行
既然 IP 能标识唯一主机、MAC 又每跳都换,那干脆把 MAC 去掉,链路层也用 IP 地址,行不行?
20.1 技术上:能
确实能实现。把链路层帧里的"源 MAC / 目的 MAC"换成"源 IP / 下一跳 IP",收到之后照样能解析、能转发。
20.2 但为什么没这么干
答案不是"做不到",而是没有必要,代价太大:
| 代价 | 说明 |
|---|---|
| 全世界的网卡驱动都要改 | 链路层与硬件绑定,改动意味着所有网卡厂商同步更新 |
| 网络层与链路层强耦合 | IP 规则一变,链路层跟着变;链路层一变,IP 也跟着变 |
| 兼容性无法保证 | 网络的发展是先从局部到整体,MAC 在前、IP 在后。现在要革新,那些老系统怎么办 |
| 投入产出不成正比 | 做了能达到的效果,不做本来就已经达到了 |
★ 历史的车轮一旦碾过,痕迹就再也无法被抹去。
✔ 用软件工程的术语说,这就是向前/向后兼容、向上/向下兼容 的约束。技术选型从来不只是"能不能做到",更是"值不值得动"。
二十一、★ 最终从宏观上看,报文一直在做什么
把整讲串起来:
主机 A:自顶向下封装
↓
路由器 1:链路层解包 → 分用到网络层 → 查路由 → 重新封装 → 发出
↓
路由器 2:解包 → 分用 → 封装 → 发出
↓
......
↓
主机 B:自底向上解包、分用,交付到应用层
★ 每经过一个路由器,都在重复「解包 → 分用 → 封装」这一套动作。