📚 第四章 IP协议
📄 一句话概括

分类地址的关键在「首位模式」:不用掩码,看开头几个比特就知道是哪一类。 这是 1981 年的设计,那时候「查表」比「算」贵。

📝 本节和前面几节的关系

4.3.2 讲了「网络位和主机位」,这一节讲「分界线怎么由首位决定」。 D 类多播和 E 类保留在这里出场,4.3.5 会把 D 类展开。

一、五类,五个前缀

第一段的数字范围和首位模式是一一对应的:

类别 首位 第一段 掩码
A 0 1 到 126 /8
B 10 128 到 191 /16
C 110 192 到 223 /24
D 多播 1110 224 到 239 —
E 保留 1111 240 到 255 —

第二列和第三列是同一件事的两种写法:「0 开头」意味着第一段小于 128,所以是 0 到 127; 「10 开头」意味着第一段在 128 到 191 之间。 所以「看第一段数字就能分类」不是巧合,是二进制前缀的直接结果。 这种设计在 1981 年是有道理的:路由器收到一个地址,只要看最高几位就能判断「网络部分多长」, 不用查表、不用配置。 在那个「内存以 KB 计」的年代,这是实打实的性能。

二、五类各占多少

按首位模式切,32 位空间被分得很整齐:

类别 占空间 地址数
A 1/2 50%
B 1/4 25%
C 1/8 12.5%
D 1/16 6.25%
E 1/16 6.25%

加起来正好 100%:因为首位模式是「前缀码」: 0、10、110、1110、1111 这五个前缀刚好把所有可能的情况分完。 这个性质在编码里叫「前缀码无歧义」,和「哈夫曼编码不会混淆」是同一个道理。 所以「分类地址切得干净」是真的:它没有重叠、没有空隙。 问题只在于「切的比例不合适」—— 一半给了 A 类(128 个网段),八分之一给了 C 类(两百多万个网段)。 这个比例反映的是 1981 年的想象:「世界上只会有一百多个大网络」。

三、A 类为什么从 1 开始

0 和 127 这两段被单独留了出来:

地址段 用途 能不能分配给机构
0.0.0.0/8 「本网络」 不能
127.0.0.0/8 回环 不能
1.0.0.0/8 到 126.0.0.0/8 可分配 能

第一行那个「本网络」是个特殊含义:0.0.0.0 表示「不知道自己的地址」, 所以 DHCP 请求的源地址就是 0.0.0.0。 而「0.0.0.0/8 里的某个地址」在早期表示「这个网络上的某台主机」,现在几乎不用了。 第二行是回环:127.0.0.1 就是「我自己」, 整个 127/8 都指向本机,所以它不消耗任何网络资源。 这也是「为什么本机服务用 127.0.0.1 访问最快」的原因——数据根本没出网卡。 所以 A 类实际能分的是 126 个:128 减掉 0 和 127 这两段。 算地址总量时用 126 还是 128,会差出 1.6%。 这个差别在「说清楚口径」时很重要,写笔记时别把两个数混着用。

四、动手 Demo:五类地址,看头几个比特就知道

先看五类的首位模式与范围,再算各类实际能分多少地址。 注意 A 类只有 126 个网段能分,0 和 127 被留用了。

blocks = [('A 类', 126, 2 ** 24), ('B 类', 16384, 2 ** 16),
          ('C 类', 2097152, 2 ** 8)]
total = 0
for name, cnt, size in blocks:
    n = cnt * size
    total += n
    print('%-5s %8d 个网 x %8d = %.3e' % (name, cnt, size, n))
print('合计 %.3e,占 %.1f%%' % (total, 100.0 * total / 2 ** 32))

实跑输出:

--------------------------------------------------------------------
五类地址,看头几个比特就知道
--------------------------------------------------------------------
**分类地址的关键在「首位模式」:不用掩码,看开头就知道是哪一类。**
**这是 1981 年的设计,那时候「查表」比「算」贵。**

  类别          首位模式     第一段范围         默认掩码
  -------------------------------------------------------
  **A**         **0**        **1 到 126**       **/8**
  **B**         **10**       **128 到 191**     **/16**
  **C**         **110**      **192 到 223**     **/24**
  D(多播)     1110         224 到 239         —
  E(保留)     1111         240 到 255         —

**第二列是「模式」,第三列是「范围的十进制写法」**:
**两者是一回事——0 开头就是 0 到 127,10 开头就是 128 到 191。**
**所以「看第一段数字就能分类」这件事,是二进制前缀的直接结果。**

**注意 A 类是从 1 开始的**:**0.0.0.0/8 被留作「本网络」,127/8 被留作回环**,
**所以 A 类实际能用的是 1 到 126 共 126 个网络。**

**算一下各类实际能分的地址总量**:
**A 类:126 个网乘 16777216,得 2.114e+09 个地址**
**B 类:16384 个网乘 65536,得 1.074e+09 个地址**
**C 类:2097152 个网乘 256,得 5.369e+08 个地址**
**三者相加 3.725e+09,占 2 的 32 次方的 86.7%**
**如果按「一个网都不浪费」算,三类正好覆盖 87.5%**,**差掉的那 0.8% 就是 0/8 和 127/8 这两段。**
**所以分类地址的问题不是「算错」,是「切得太粗」**——
**A 类一个网段 1677 万个地址,谁拿了都用不完。**

86.7% 和 87.5% 这两个数要分清: 87.5% 是「A、B、C 三类理论上占的空间」(1/2 加 1/4 加 1/8); 86.7% 是「扣掉 0/8 和 127/8 之后实际能分的」。差的那 0.8% 就是这两段。 写文档时用哪个数,取决于「你说的是理论还是实际」。 「首位模式」这套设计有个现代版的继承者:IPv6 的格式前缀。 2000::/3 是全局单播、fe80::/10 是链路本地、fc00::/7 是唯一本地—— 思路完全一样:看开头几位就知道「这地址干什么用的」。 区别是 IPv6 的前缀可以很长,不必挤在「首位」那么几个比特里。 最后说一个「分类地址还在用的地方」:很多系统的「地址类型判断」还是按老规矩写的, 比如「10 开头是内网」「192.168 开头是内网」。 这些判断在 CIDR 时代其实不严谨(10.0.0.0/8 只是个前缀), 但因为「私有段恰好是按类别挑的」,所以一直没出事。

30 秒实验

  1. 算一下:126 个 A 类网段一共覆盖多少地址?占 2 的 32 次方多少?
  2. 想一下:为什么 127/8 整段都指向本机?
  3. 想一下:首位模式为什么能做到「无歧义」?

常见误区

  1. 以为「A 类有 256 个网段」。 只有 128 个 /8,能分的是 126 个。
  2. 以为「分类是软件规定的」。 是首位模式的数学结果,看第一段数字就能判断。
  3. 以为「分类地址完全没用了」。 现代地址分类判断还按它写, IPv6 的前缀设计也继承了同一思路。
自测三问(点开对答案) 1. B 类的首位模式是什么? —— **10**,所以第一段是 128 到 191,默认掩码 /16。 2. 五类加起来为什么正好 100%? —— **0、10、110、1110、1111 这五个前缀把 32 位空间分完了**,没有重叠也没有空隙。 3. A 类为什么只有 126 个可用网段? —— **0.0.0.0/8 留给「本网络」、127.0.0.0/8 留给回环**,128 减 2 得 126。

下一节看广播地址:主机位全 1 的那个特殊值。

相关笔记