层次性就是:地址里有一段表示「在哪张网」,一段表示「网里哪台」。 没有层次性,路由表就得记住每一台主机——那是不可能维护的。
1.8.1 讲的是「唯一」,这一节讲「分层」。 这一节会出现二进制对照,因为层次性只有按位看才清楚。
一、地址里有两段
拿本机地址 192.168.3.152/24 拆开看:
| 项 | 点分十进制 | 二进制 |
|---|---|---|
| IP | 192.168.3.152 | 11000000 10101000 00000011 10011000 |
| 掩码 | 255.255.255.0 | 11111111 11111111 11111111 00000000 |
| 网络部分 | 192.168.3.0 | 11000000 10101000 00000011 00000000 |
| 主机部分 | 0.0.0.152 | 00000000 00000000 00000000 10011000 |
| 广播地址 | 192.168.3.255 | 11000000 10101000 00000011 11111111 |
掩码的作用是「划一条线」:前 24 位是 1,就表示「前 24 位属于网络部分」。 IP 与掩码做按位与,得到网络地址;剩下的就是主机地址。 第三行与第四行加起来正好是原地址:192.168.3.0 加 0.0.0.152 就是 192.168.3.152。 这个关系不是巧合,是定义的直接结果。 第五行的广播地址算法是「网络部分不变、主机部分全 1」:把最后 8 位全变成 1,就是 255。 所以 /24 的广播地址永远是「前三段不变、最后一段 255」。
二、层次性买到了什么
买到了「路由表能压缩」:
| 如果地址没有层次 | 有层次之后 |
|---|---|
| 每条路由记一台主机 | 一条路由记一个网段 |
| 百台设备要百条 | 一个 /24 只占一条 |
| 全球路由表不可维护 | 路由表能控制在百万级 |
第二行是量级上的差别:一个有 250 台设备的网段,如果没有层次性,路由表里就要写 250 条; 有层次性只写一条 192.168.3.0/24。 这就是「聚合」——把一堆明细压成一条。 第三行是互联网能运转的前提:今天全球路由表大约一百万条, 如果没有层次性,这个数会是几十亿,任何路由器都存不下。 所以「地址必须带层次」不是设计偏好,是规模逼出来的。 层次性也解释了「为什么不能随便改 IP」:IP 的网络部分决定了你在哪张网里, 改错了就出不去,或者出去了回不来。
三、MAC 也有层次,但在厂商那里
两种地址的层次结构对应两种转发方式:
| 地址 | 层次在哪 | 谁看它做决定 |
|---|---|---|
| IP | 网络部分 / 主机部分 | 路由器(按网络部分) |
| MAC | OUI / 厂商编号 | 交换机(按整张表) |
第二行那个「按整张表」是关键差别:交换机不解析 MAC 的层次, 它是靠「学到的表」——哪个 MAC 从哪个口来。 所以 MAC 的层次性对转发没有帮助,它只是厂商管理的产物,不是转发机制的一部分。 这就解释了为什么大型二层网络容易出问题: 交换机只能靠「泛洪 + 学习」,MAC 表一大多,广播与未知单播就把带宽吃掉了。 而路由器能按网段聚合,天然有扩展性——这就是「大网络要三层到边缘」的由来。 记住这个分工:看 IP 的网络部分决定「往哪条路走」,看 MAC 决定「这一跳交给谁」。 1.9 节的交换机和路由器,就是按这个分工分开的。
四、动手 Demo:地址的层次性,网络部分与主机部分
把本机地址按位拆成网络部分与主机部分,再算广播地址。 点分十进制看不出的东西,二进制一眼就看出来。
import socket, psutil
ip, mask = '192.168.3.152', '255.255.255.0'
def bits(v):
return '.'.join(format(int(x), '08b') for x in v.split('.'))
n = (lambda s: sum(int(x) << (8 * (3 - i))
for i, x in enumerate(s.split('.'))))
ipn, mkn = n(ip), n(mask)
net, host = ipn & mkn, ipn & (~mkn & 0xFFFFFFFF)
bc = net | (~mkn & 0xFFFFFFFF)
for tag, v in (('IP', ipn), ('掩码', mkn), ('网络部分', net),
('主机部分', host), ('广播地址', bc)):
d = '.'.join(str((v >> (8 * (3 - i))) & 255) for i in range(4))
print('%-10s %-18s %s' % (tag, d, bits(d)))
实跑输出:
--------------------------------------------------------------------
地址的层次性,网络部分与主机部分
--------------------------------------------------------------------
**层次性的意思是:地址里有一段表示「在哪张网」,一段表示「网里哪台」。**
本机地址 192.168.3.152,掩码 255.255.255.0(即 /24)。
项 点分十进制 二进制
----------------------------------------------------------------
IP 192.168.3.152 11000000101010000000001110011000
掩码 255.255.255.0 11111111111111111111111100000000
网络部分 192.168.3.0 11000000101010000000001100000000
主机部分 0.0.0.152 00000000000000000000000010011000
广播地址 192.168.3.255 11000000101010000000001111111111
**前 24 位是网络部分,后 8 位是主机部分**——**路由器只关心前一部分,交换机只关心 MAC。**
**MAC 地址也有层次,只是层次在厂商那里**:
OUI 9C-B6-D0(厂商)+ 序号 0D-D5-0F(厂商内部编号)
**两种层次结构对应两种转发方式**:
**看 IP 的网络部分决定「往哪条路走」,看 MAC 决定「这一跳交给谁」。**
**这就是交换机与路由器的分工,1.9 节会展开。**
掩码的二进制是 24 个 1 加 8 个 0,
这就是「/24」这个写法的来源——斜杠后面的数字就是 1 的个数。
网络部分与主机部分加起来正好是原地址:192.168.3.0 加 0.0.0.152 等于 192.168.3.152。
这个可加性是「按位切分」的直接结果。
广播地址等于「网络部分 + 主机部分全 1」:代码里就是 net | (~mkn),
按位或把主机部分全部置 1。
所以 /24 的广播地址永远是最后一段 255。
30 秒实验
- 把掩码改成
255.255.255.192(/26),再跑一遍——看网络部分与广播地址各变成什么。 - 把 IP 改成
10.1.2.3、掩码255.0.0.0(/8),算一下这个网段能装多少台主机。 - 想一下:为什么
192.168.3.0与192.168.3.255都不能分配给主机?
常见误区
- 以为掩码只是「另一种写法」。 它是「划线工具」:标出哪几位属于网络部分, 直接决定网段大小。
- 以为 MAC 的层次性能帮交换机转发。 交换机靠学习表,不解析 OUI。 所以大型二层网络扩展性差。
- 以为 IP 可以随便改。 网络部分决定了你在哪张网里,改错了就出不去或者回不来。
自测三问(点开对答案)
1. 「/24」这个写法是什么意思? —— **掩码前 24 位是 1**,也就是 255.255.255.0。斜杠后的数字就是掩码里 1 的个数。 2. 层次性带来了什么实际好处? —— **路由表能聚合**:一个 /24 网段只占一条路由,而不是每个主机一条。 没有它,全球路由表会大到无法维护。 3. 为什么说 MAC 的层次性对转发没有帮助? —— **交换机靠「学到的表」转发,不解析 OUI 层次。**所以大型二层网络只能靠泛洪与学习,扩展性差。下一节进入 1.9:网络的构成要素——网线、网卡、中继器、交换机、路由器各干什么。
- ☐ (本节完,下一节 1.9.1 通信媒介与数据链路)