子网掩码计算方法(教程:从二进制到可用主机数速算)

刚拿到 192.168.10.0/26 这种写法,第一反应往往是这网段到底能塞几台机器。结论可以一句话给出:可用主机数等于 2 的(32 减去前缀长度)次方再减 2,/26 的主机位是 6 位,2^6 − 2 = 62 台。做网段规划时,这套换算只需要三步——先把前缀长度换成点分十进制掩码,再算出网络号与广播地址,最后用反查规则验一遍。步骤走完,掩码、网段边界、可用地址区间就都出来了。

准备:掩码位数与主机位数的对应关系

掩码位数就是网络位的个数,主机位数等于 32 减去这个数,两者一一对应,没有第三种可能。IPv4 地址一共 32 位,掩码从左往右连续排 1,1 的数量就是前缀长度,剩下的位数留给主机。理解这一层,后面所有公式都是顺推。

常见翻车点是把方向记反:前缀长度数字越大,网段越小。/24 有 8 位主机位,能装 254 台;/26 只剩 6 位主机位,只能装 62 台。有人看到 26 比 24 大,就以为网段更大,划完发现地址不够用,只能返工重划,连带着 DHCP 地址池和防火墙策略一起改。

横向展开对比几个常用前缀,主机位每减 1 位,可用地址就少一半:

前缀长度 主机位数 点分十进制掩码 总地址数 可用主机数
/24 8 255.255.255.0 256 254
/25 7 255.255.255.128 128 126
/26 6 255.255.255.192 64 62
/27 5 255.255.255.224 32 30
/28 4 255.255.255.240 16 14
/29 3 255.255.255.248 8 6
/30 2 255.255.255.252 4 2

这张表建议直接抄进规划文档。真正的取舍落在 /30 与 /31 之间:/30 给两台路由器之间的点对点链路留出 2 个可用地址,通用性好;/31 按 RFC 3021 把两个地址都当主机地址用,省掉一半地址空间,代价是两端设备都要支持这种写法,老设备上会配不通。

把两个容易记混的前缀并排看,差异集中在几个维度上:

维度 /24 /26 结论
主机位数 8 6 前缀每加 1 位,主机位减 1
掩码末字节 0 192 从 128 起按 128、64、32 累加
子网步长 256 − 0 = 256 256 − 192 = 64 步长等于每个子网块的地址数
可用主机数 254 62 均为总地址数减去保留的两个
典型用途 单一办公网段 按部门或业务切分 需要隔离时选更长的前缀

两个前缀的可用地址数相差数倍,配置工作量却几乎一样,所以隔离需求一出现,往下切分通常比在同一网段里做策略更省事。

执行:把前缀长度换成点分十进制掩码

换算方法只有一句话:从左往右写满前缀长度个 1,其余补 0,再按每 8 位一组转成十进制。/26 就是 26 个 1 加 6 个 0,切成四段是 11111111.11111111.11111111.11000000,逐段加权得到 255.255.255.192。

具体操作按下面五步走:

  1. 写出 32 位二进制,前 N 位填 1,其余填 0。
  2. 按 8 位一组,从左到右切成四段。
  3. 每段按 128、64、32、16、8、4、2、1 加权求和。
  4. 用点号连接四段,得到点分十进制掩码。
  5. 记下末段的值,后面算子网步长要用。

末段值的累加规律

末段的值不是随便来的,它是 128 之后的累加:/25 是 128,/26 是 128 + 64 = 192,/27 是 192 + 32 = 224。记不住表的时候,按这个累加规律现推,比翻文档快得多,也不容易记混。

让函数一次算清整张表

下面这段代码把上面五步封成函数,输入前缀长度,直接输出掩码与可用地址数:

def prefix_to_mask(prefix: int) -> str:
    """把 CIDR 前缀长度转成点分十进制掩码。"""
    if not 0 <= prefix <= 32:
        raise ValueError("前缀长度必须在 0 到 32 之间")
    bits = "1" * prefix + "0" * (32 - prefix)
    return ".".join(str(int(bits[i:i + 8], 2)) for i in range(0, 32, 8))

def usable_hosts(prefix: int) -> int:
    """可用主机数 = 2^主机位 - 2,/31 与 /32 单独处理。"""
    host_bits = 32 - prefix
    if prefix == 32:
        return 1
    if prefix == 31:
        return 2
    return 2 ** host_bits - 2

for p in (24, 25, 26, 27, 28, 29, 30, 31, 32):
    print(f"/{p:<2} {prefix_to_mask(p):<16} 可用 {usable_hosts(p)}")

注意最后两行的分支判断:前缀到 31 和 32 时公式不再减 2,直接返回 2 和 1。漏掉这个判断,脚本会把 /31 点对点链路算成 0 个可用地址,规划时白白浪费一整段地址。

执行:算网络号、广播地址与可用主机数

网络号由 IP 与掩码按位做与运算得到,广播地址是把主机位全部置 1 的结果,可用主机数就是这两个地址之间、除它们自身以外的地址个数。三步是递进关系,前一步错了后面全错。

以 192.168.10.66/26 为例,操作顺序如下:

  1. 由前缀 26 得出子网步长,256 − 192 = 64。
  2. 用末位 66 除以 64,得商 1,说明落在第 2 个地址块。
  3. 网络号末字节为 64,完整网络号是 192.168.10.64。
  4. 广播地址末字节为 64 + 64 − 1 = 127,即 192.168.10.127。
  5. 可用区间是 192.168.10.65 到 192.168.10.126,共 62 个。

子网步长这个中间量值得单独记牢:它等于 256 减去掩码末字节的值,也等于每个子网块包含的地址总数。/26 的步长是 64,整段地址的块起点就是 0、64、128、192,末位 66 落进 64 那一块,不用转二进制也能判断归属。

手工推几个网段还行,网段一多就该交给脚本。下面这段用标准库一次性输出网段的整套参数,顺带判断某个 IP 属于哪个子网:

import ipaddress

net = ipaddress.IPv4Network("192.168.10.0/26")
print("网络号    ", net.network_address)
print("广播地址  ", net.broadcast_address)
print("掩码      ", net.netmask)
print("可用主机数", net.num_addresses - 2)
print("可用区间  ", f"{list(net.hosts())[0]} - {list(net.hosts())[-1]}")

for cidr in ("192.168.10.0/26", "192.168.10.64/26", "192.168.10.128/26"):
    sub = ipaddress.IPv4Network(cidr)
    print(cidr, "->", ipaddress.IPv4Address("192.168.10.66") in sub)

标准库的好处是把边界情况一起处理掉了,网络号和广播地址不会被误当成可用地址。需要留意的一点是,构造 IPv4Network 时默认要求主机位为 0,直接写 192.168.10.66/26 会抛异常,得加 strict=False 才会按掩码截断到网络号。

验证:三条反查规则确认结果没算错

验证只看三处:网络号末字节是不是步长的整数倍、广播地址是不是下一块起点减一、可用地址数是不是等于 2 的主机位次方减 2。三条都对上,结果基本可以放心用。

按顺序核对:

  1. 用网络号末字节除以步长,余数为 0 才算通过。
  2. 用网络号加步长再减 1,看是否等于广播地址。
  3. 用广播地址减网络号再减 1,看可用数是否吻合。
  4. 把网关地址放进可用区间内,避开首末两个地址。
  5. 用 ping 确认首末两个地址都不通,说明边界划分正确。

网关与首末地址的分配约定

第 4 步最容易被跳过。网关习惯取第一个可用地址,也就是网络号加一,DHCP 地址池从网关之后开始分配,排查地址冲突时一眼就能定位是哪一段。至于 /32,它表示单个主机地址,多用于环回口和主机路由,不参与子网划分,别把它当成只挂一台机器的普通网段去配网关。

到这里,从二进制掩码到可用主机数的整条换算链路就走完了。步骤不多,但每一步都建议用反查规则兜一遍,网段规划出错后返工的成本,远高于多算两遍。

常见问题(FAQ)

Q1:/26 网段到底能接多少台设备?

62 台。总地址 64 个,扣掉网络号和广播地址各一个,剩下的才能分配给设备。

Q2:为什么可用主机数要减 2?

首地址是网络号,末地址是广播地址,两者都不能配给主机,所以要从总数里减掉。

Q3:/31 和 /32 能不能当普通网段用?

不能。两者属于点对点链路与单主机路由场景,没有网络号和广播地址的分配概念。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 qiqicto@qq.com 举报,一经查实,本站将立刻删除。
赞 (0)
拓扑大师的头像拓扑大师普通用户

相关推荐

返回顶部