bigywater.tech
网络协议 · 10

子网划分与 CIDR:用代码算网络号、广播地址与可用主机数

/22、/26、255.255.252.0、通配符 0.0.3.255……子网划分的各种写法到底怎么互相换算?怎么给几个部门分配地址才不重叠?什么时候能聚合路由?这篇用代码把规则算一遍,再对照本机真实的路由表。

2^(32−n) − 2
前缀长度为 n 时可用的主机数(/22 是 1022,/26 是 62)
8 → 1
8 个对齐的连续 /24 聚合成 1 条 /21;没对齐的 4 个只能合成 3 条
254 ms vs 36 ms
100 万次“IP 是否在子网内”判断:ipaddress 对象与整数位运算

前缀、掩码、通配符

实测 · 本机执行输出
  10.1.2.200/8       掩码 255.0.0.0        通配符 0.255.255.255 网络号 10.0.0.0      广播 10.255.255.255  可用主机 16777214 范围 10.0.0.1 ~ 10.255.255.254
  10.1.2.200/16      掩码 255.255.0.0      通配符 0.0.255.255  网络号 10.1.0.0      广播 10.1.255.255    可用主机 65534  范围 10.1.0.1 ~ 10.1.255.254
  10.1.2.200/22      掩码 255.255.252.0    通配符 0.0.3.255    网络号 10.1.0.0      广播 10.1.3.255      可用主机 1022   范围 10.1.0.1 ~ 10.1.3.254
  10.1.2.200/24      掩码 255.255.255.0    通配符 0.0.0.255    网络号 10.1.2.0      广播 10.1.2.255      可用主机 254    范围 10.1.2.1 ~ 10.1.2.254
  172.16.5.9/20      掩码 255.255.240.0    通配符 0.0.15.255   网络号 172.16.0.0    广播 172.16.15.255   可用主机 4094   范围 172.16.0.1 ~ 172.16.15.254
  192.0.2.77/26      掩码 255.255.255.192  通配符 0.0.0.63     网络号 192.0.2.64    广播 192.0.2.127     可用主机 62     范围 192.0.2.65 ~ 192.0.2.126
  192.0.2.77/28      掩码 255.255.255.240  通配符 0.0.0.15     网络号 192.0.2.64    广播 192.0.2.79      可用主机 14     范围 192.0.2.65 ~ 192.0.2.78
  192.0.2.77/30      掩码 255.255.255.252  通配符 0.0.0.3      网络号 192.0.2.76    广播 192.0.2.79      可用主机 2      范围 192.0.2.77 ~ 192.0.2.78
  规律:前缀每加 1 位,地址数减半;可用主机数 = 2^(32−前缀) − 2

前缀长度 n、点分掩码和通配符(掩码取反)是同一件事的三种写法;网络号 = 地址 AND 掩码,广播 = 网络号 OR 通配符。

/31 与 /32

实测 · 本机执行输出
  192.0.2.4/30: 共 4 个地址,地址列表 ['192.0.2.4', '192.0.2.5', '192.0.2.6', '192.0.2.7']
  192.0.2.4/31: 共 2 个地址,地址列表 ['192.0.2.4', '192.0.2.5']
  192.0.2.4/32: 共 1 个地址,地址列表 ['192.0.2.4']
  ipaddress 的 hosts() 在 /31 上返回两个地址,在 /32 上返回一个,与 RFC 3021 / 主机路由的约定一致:[2, 2, 1]

/31 没有网络号和广播,用于点对点链路;/32 是单个主机。

划分

实测 · 本机执行输出
  部门 A:需要 60  台 → 10.0.0.0/26      (可用 62  台,浪费 2 个)
  部门 B:需要 28  台 → 10.0.0.64/27     (可用 30  台,浪费 2 个)
  部门 C:需要 12  台 → 10.0.0.96/28     (可用 14  台,浪费 2 个)
  部门 D:需要 2   台 → 10.0.0.112/30    (可用 2   台,浪费 0 个)
  四个子网互不重叠: True;用掉 116 个地址,/24 里还剩 140 个

VLSM 要按大小从大到小分配,起点必须对齐到自己的大小,这样才不会重叠和碎片化。

聚合

实测 · 本机执行输出
  10.8.0.0/24 ~ 10.8.7.0/24 合并 → [IPv4Network('10.8.0.0/21')]
  10.8.1.0/24 ~ 10.8.4.0/24(从 1 开始,没有对齐到 4 的倍数)→ [IPv4Network('10.8.1.0/24'), IPv4Network('10.8.2.0/23'), IPv4Network('10.8.4.0/24')]
  10.8.0.0/24, .1, .2, .4(缺 .3)→ [IPv4Network('10.8.0.0/23'), IPv4Network('10.8.2.0/24'), IPv4Network('10.8.4.0/24')]
  聚合要求:个数是 2 的幂、起点按这个大小对齐(/21 的起点必须是 8 的倍数),否则只能合并一部分

相邻子网要个数是 2 的幂、起点对齐才能合并成一条。

成员判断

实测 · 本机执行输出
  100 万个 172.16.0.0/16 里的随机地址,落在 172.16.0.0/20 内的有 62318 个(位运算算出 62318 个,一致)
  ipaddress.ip_address() in network: 254 ms;整数 (ip & mask) == network: 36 ms,快 7 倍——路由器做最长前缀匹配就是在做这个运算

(ip AND mask) == network 是一切路由与访问控制的基础,用整数比用对象快一个数量级。

路由表写法

实测 · 本机执行输出
  路由表共 198 条目的地;前缀长度分布: /0×1, /4×1, /22×1, /32×195
  default            <本机局域网IP>       UGScg                 en0       
  127                127.0.0.1          UCS                   lo0       
  169.254            link#14            UCS                   en0      !
  <本机局域网IP>/22       link#14            UCS                   en0      !
  224.0.0/4          link#14            UmCS                  en0      !
  255.255.255.255/32 link#14            UCS                   en0      !
  另有 33 条 169.254.x.x 的主机路由(同网段邻居的 ARP 条目,标志 UHLSW,不逐条列出)
  netstat 把目的地的尾部 0 省略写(127 = 127.0.0.0/8,169.254 = 169.254.0.0/16),/N 给出前缀长度;default 就是 0.0.0.0/0

netstat 里目的地末尾的 0 被省略:127 就是 127.0.0.0/8,default 就是 0.0.0.0/0。

分步演示

子网与 CIDR
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64(Apple 芯片)/ Python 3.14.8 / tcpdump(libpcap)/ scapy 2.8 / dpkt / dnspython / h2 / aioquic / OpenSSL / curl 8.7.1;抓包在 lo0(环回)上做,少数实验用真实网卡 en0(这台机器上 en0 是 Wi-Fi,tcpdump 看到的是系统转成以太网格式的帧,所以文中的“以太网头”都指这个 14 字节的头)或访问公网(会在文章里注明);需要丢包 / 延迟 / 限速时,用一个只作用于 lo0 端口 9400-9499 的 dummynet 辅助脚本(netlab);所有服务端都是本机自己起的进程;时间戳取自 tcpdump 的 -tt,数字每次运行会有小幅抖动。第一到五节是 Python ipaddress 的计算和计时(单次、100 万次随机地址),用的是文档保留地址 10.x、172.16.x、192.0.2.x;第六节读本机路由表,局域网地址与 MAC 做了遮盖
    • 没有验证:真实路由器上的聚合与 BGP 通告;给接口配置 /31;VLSM 在真实网络里的重编址;IPv6 的前缀划分(见 IPv6 一组);路由表查找的数据结构(Patricia / 多比特 trie)
    京ICP备2026067502号-1京公网安备11010502063487号