第9天:子网划分实战
“子网划分就像把一栋大楼分成不同的房间。”
📚 今日目标
- 理解子网掩码的概念和作用
- 掌握CIDR表示法
- 学会计算网络地址、广播地址
- 能够进行子网划分
- 编写子网计算器工具
🎯 为什么需要子网划分?
生活中的例子
没有子网划分:
一栋100层的大楼,所有人共用一个门牌号
→ 混乱、难以管理
有子网划分:
把大楼分成不同楼层,每层有自己的编号
→ 清晰、便于管理
网络也是一样:
- 节省IP地址
- 提高网络性能
- 增强安全性
- 便于管理
实际问题
问题:一个公司有500台电脑,给了一个C类地址192.168.1.0
C类地址只能容纳254台主机(2^8 - 2)
解决方案:
1. 申请多个C类地址(浪费、管理复杂)
2. 使用B类地址,然后划分子网(推荐)
📊 子网掩码
什么是子网掩码?
子网掩码(Subnet Mask)用于区分IP地址中的网络部分和主机部分。
IP地址: 192.168.1.100
子网掩码: 255.255.255.0
作用:确定哪些位是网络号,哪些位是主机号
子网掩码的格式
二进制表示:
网络部分:全是1
主机部分:全是0
例如:255.255.255.0
11111111.11111111.11111111.00000000
[ 网络部分(24位) ][主机部分(8位)]
常见的子网掩码
| 类别 | 默认子网掩码 | 二进制 | CIDR |
|---|---|---|---|
| A类 | 255.0.0.0 | 11111111.00000000.00000000.00000000 | /8 |
| B类 | 255.255.0.0 | 11111111.11111111.00000000.00000000 | /16 |
| C类 | 255.255.255.0 | 11111111.11111111.11111111.00000000 | /24 |
🔢 CIDR表示法
什么是CIDR?
CIDR(Classless Inter-Domain Routing,无类域间路由)
用 /数字 表示子网掩码,数字表示网络位数。
传统表示:192.168.1.0 子网掩码:255.255.255.0
CIDR表示:192.168.1.0/24
/24 表示前24位是网络位,后8位是主机位
CIDR对照表
| CIDR | 子网掩码 | 可用主机数 | 说明 |
|---|---|---|---|
| /8 | 255.0.0.0 | 16,777,214 | A类默认 |
| /16 | 255.255.0.0 | 65,534 | B类默认 |
| /24 | 255.255.255.0 | 254 | C类默认 |
| /25 | 255.255.255.128 | 126 | C类分2个子网 |
| /26 | 255.255.255.192 | 62 | C类分4个子网 |
| /27 | 255.255.255.224 | 30 | C类分8个子网 |
| /28 | 255.255.255.240 | 14 | C类分16个子网 |
| /29 | 255.255.255.248 | 6 | C类分32个子网 |
| /30 | 255.255.255.252 | 2 | 点对点链路 |
计算公式
网络位数:n
主机位数:32 - n
可用主机数 = 2^(主机位数) - 2
减2的原因:
- 网络地址(主机位全0)
- 广播地址(主机位全1)
例如:/24
主机位数 = 32 - 24 = 8
可用主机数 = 2^8 - 2 = 254
🧮 子网划分计算
基本概念
网络地址:主机位全为0 广播地址:主机位全为1 第一个可用IP:网络地址 + 1 最后一个可用IP:广播地址 - 1
计算步骤
例1:192.168.1.0/24
1. IP地址:192.168.1.0
2. 子网掩码:255.255.255.0 (/24)
计算:
网络地址:192.168.1.0
广播地址:192.168.1.255
第一个可用IP:192.168.1.1
最后一个可用IP:192.168.1.254
可用主机数:254
例2:192.168.1.0/25
1. IP地址:192.168.1.0
2. 子网掩码:255.255.255.128 (/25)
分析:
/25 表示前25位是网络位,后7位是主机位
255.255.255.128 = 11111111.11111111.11111111.10000000
子网1:
网络地址:192.168.1.0
广播地址:192.168.1.127
可用IP:192.168.1.1 - 192.168.1.126
可用主机数:126
子网2:
网络地址:192.168.1.128
广播地址:192.168.1.255
可用IP:192.168.1.129 - 192.168.1.254
可用主机数:126
快速计算技巧
1. 找到"变化的八位"
255.255.255.128 → 最后一个八位是128
2. 计算块大小
块大小 = 256 - 子网掩码最后非0的八位
块大小 = 256 - 128 = 128
3. 列出子网
第一个子网:0
第二个子网:0 + 128 = 128
第三个子网:128 + 128 = 256(超出范围,没有第三个)
所以子网是:
192.168.1.0/25
192.168.1.128/25
🔧 实战项目:子网计算器
让我们编写一个强大的子网计算器!
代码实现
# day09_subnet_calculator.py
# 功能:子网计算器
import math
class SubnetCalculator:
"""子网计算器"""
def __init__(self):
pass
def cidr_to_mask(self, cidr):
"""
将CIDR转换为子网掩码
参数:
cidr: CIDR值(如24)
返回:
子网掩码字符串(如 "255.255.255.0")
"""
# 生成32位二进制,前cidr位是1,其余是0
binary = '1' * cidr + '0' * (32 - cidr)
# 分成4组,每组8位
octets = [binary[i:i+8] for i in range(0, 32, 8)]
# 转换为十进制
mask = '.'.join([str(int(octet, 2)) for octet in octets])
return mask
def mask_to_cidr(self, mask):
"""
将子网掩码转换为CIDR
参数:
mask: 子网掩码字符串(如 "255.255.255.0")
返回:
CIDR值
"""
# 转换为二进制
binary = ''.join([format(int(x), '08b') for x in mask.split('.')])
# 计算1的个数
return binary.count('1')
def ip_to_int(self, ip):
"""将IP地址转换为整数"""
parts = ip.split('.')
return (int(parts[0]) << 24) + (int(parts[1]) << 16) + \
(int(parts[2]) << 8) + int(parts[3])
def int_to_ip(self, num):
"""将整数转换为IP地址"""
return f"{(num >> 24) & 255}.{(num >> 16) & 255}." \
f"{(num >> 8) & 255}.{num & 255}"
def calculate_subnet(self, ip, cidr):
"""
计算子网信息
参数:
ip: IP地址字符串
cidr: CIDR值
返回:
包含所有子网信息的字典
"""
# 转换为整数
ip_int = self.ip_to_int(ip)
# 计算子网掩码
mask = self.cidr_to_mask(cidr)
mask_int = self.ip_to_int(mask)
# 计算网络地址(IP AND 掩码)
network_int = ip_int & mask_int
network = self.int_to_ip(network_int)
# 计算广播地址(网络地址 OR 反码掩码)
wildcard_int = ~mask_int & 0xFFFFFFFF # 通配符掩码(反码)
broadcast_int = network_int | wildcard_int
broadcast = self.int_to_ip(broadcast_int)
# 计算第一个和最后一个可用IP
first_usable_int = network_int + 1
last_usable_int = broadcast_int - 1
first_usable = self.int_to_ip(first_usable_int)
last_usable = self.int_to_ip(last_usable_int)
# 计算主机数
host_bits = 32 - cidr
total_hosts = 2 ** host_bits
usable_hosts = total_hosts - 2 if total_hosts > 2 else 0
# 计算通配符掩码
wildcard = self.int_to_ip(wildcard_int)
result = {
'ip': ip,
'cidr': cidr,
'mask': mask,
'wildcard': wildcard,
'network': network,
'broadcast': broadcast,
'first_usable': first_usable,
'last_usable': last_usable,
'total_hosts': total_hosts,
'usable_hosts': usable_hosts
}
return result
def split_subnet(self, ip, old_cidr, new_cidr):
"""
将一个子网划分为多个更小的子网
参数:
ip: 原始网络地址
old_cidr: 原始CIDR
new_cidr: 新的CIDR(必须大于old_cidr)
返回:
子网列表
"""
if new_cidr <= old_cidr:
return None
# 计算可以划分多少个子网
num_subnets = 2 ** (new_cidr - old_cidr)
# 计算每个子网的大小
subnet_size = 2 ** (32 - new_cidr)
# 获取起始网络地址
start_int = self.ip_to_int(ip) & self.ip_to_int(self.cidr_to_mask(old_cidr))
subnets = []
for i in range(num_subnets):
subnet_ip_int = start_int + (i * subnet_size)
subnet_ip = self.int_to_ip(subnet_ip_int)
subnets.append(f"{subnet_ip}/{new_cidr}")
return subnets
def print_subnet_info(self, info):
"""
打印子网信息
参数:
info: calculate_subnet()返回的字典
"""
print("=" * 70)
print("子网信息".center(70))
print("=" * 70)
print(f"\n📍 IP地址: {info['ip']}")
print(f"🔢 CIDR: /{info['cidr']}")
print(f"🎭 子网掩码: {info['mask']}")
print(f"🃏 通配符掩码: {info['wildcard']}")
print(f"\n🌐 网络地址: {info['network']}/{info['cidr']}")
print(f"📡 广播地址: {info['broadcast']}")
print(f"\n🏁 第一个可用IP: {info['first_usable']}")
print(f"🏁 最后一个可用IP: {info['last_usable']}")
print(f"\n📊 总主机数: {info['total_hosts']}")
print(f"✅ 可用主机数: {info['usable_hosts']}")
print("=" * 70)
def main():
"""
主函数
"""
calc = SubnetCalculator()
print("=" * 70)
print("子网计算器".center(70))
print("=" * 70)
while True:
print("\n请选择功能:")
print("1. 计算子网信息")
print("2. CIDR ↔ 子网掩码转换")
print("3. 子网划分")
print("4. 快速查询常用CIDR")
print("0. 退出")
choice = input("\n请输入选项: ").strip()
if choice == '0':
print("\n再见!")
break
elif choice == '1':
ip = input("\n请输入IP地址: ").strip()
cidr = input("请输入CIDR(如24): ").strip()
try:
cidr = int(cidr)
if 0 <= cidr <= 32:
info = calc.calculate_subnet(ip, cidr)
calc.print_subnet_info(info)
else:
print("❌ CIDR必须在0-32之间")
except ValueError:
print("❌ 请输入有效的数字")
elif choice == '2':
print("\n请选择转换方向:")
print("1. CIDR → 子网掩码")
print("2. 子网掩码 → CIDR")
sub_choice = input("请输入选项: ").strip()
if sub_choice == '1':
cidr = input("\n请输入CIDR: ").strip()
try:
cidr = int(cidr)
mask = calc.cidr_to_mask(cidr)
print(f"\n/{cidr} = {mask}")
except ValueError:
print("❌ 请输入有效的数字")
elif sub_choice == '2':
mask = input("\n请输入子网掩码: ").strip()
try:
cidr = calc.mask_to_cidr(mask)
print(f"\n{mask} = /{cidr}")
except:
print("❌ 请输入有效的子网掩码")
elif choice == '3':
ip = input("\n请输入网络地址: ").strip()
old_cidr = input("请输入原始CIDR: ").strip()
new_cidr = input("请输入新的CIDR: ").strip()
try:
old_cidr = int(old_cidr)
new_cidr = int(new_cidr)
subnets = calc.split_subnet(ip, old_cidr, new_cidr)
if subnets:
print(f"\n📊 将 {ip}/{old_cidr} 划分为 /{new_cidr} 子网:")
print(f" 共 {len(subnets)} 个子网\n")
for i, subnet in enumerate(subnets, 1):
print(f" {i}. {subnet}")
else:
print("❌ 新CIDR必须大于原CIDR")
except ValueError:
print("❌ 请输入有效的数字")
elif choice == '4':
print("\n常用CIDR速查表:")
print(f"\n{'CIDR':<8} {'子网掩码':<18} {'可用主机数':<12} {'说明'}")
print("-" * 60)
common_cidrs = [
(8, "A类默认"),
(16, "B类默认"),
(24, "C类默认"),
(25, "C类分2个子网"),
(26, "C类分4个子网"),
(27, "C类分8个子网"),
(28, "C类分16个子网"),
(29, "小型子网"),
(30, "点对点链路"),
]
for cidr, desc in common_cidrs:
mask = calc.cidr_to_mask(cidr)
hosts = 2 ** (32 - cidr) - 2
print(f"/{cidr:<7} {mask:<18} {hosts:<12} {desc}")
if __name__ == "__main__":
main()
运行程序
python code/day09/day09_subnet_calculator.py
💡 实战案例
案例1:公司网络规划
需求:
公司有200台电脑,分布在4个部门
- 销售部:60台
- 技术部:80台
- 行政部:40台
- 财务部:20台
给定网络:192.168.0.0/24
方案:
1. 技术部:192.168.0.0/25(126台主机)
2. 销售部:192.168.0.128/26(62台主机)
3. 行政部:192.168.0.192/27(30台主机)
4. 财务部:192.168.0.224/27(30台主机)
案例2:家庭网络
需求:
家里有10台设备,使用C类私网
方案:
网络:192.168.1.0/24
- 可用IP:192.168.1.1 - 192.168.1.254
- 路由器:192.168.1.1
- 设备:192.168.1.100-109
🎓 知识小结
今天学习了:
- ✅ 子网掩码用于区分网络部分和主机部分
- ✅ CIDR是子网掩码的简写形式
- ✅ 可用主机数 = 2^主机位数 - 2
- ✅ 网络地址、广播地址的计算方法
- ✅ 子网划分的实际应用
重要公式
可用主机数 = 2^(32-CIDR) - 2
子网数量 = 2^(新CIDR - 旧CIDR)
块大小 = 256 - 子网掩码的变化八位
💪 练习题
练习1:基础计算
计算以下子网的信息:
- 192.168.10.0/24
- 172.16.0.0/16
- 10.0.0.0/8
练习2:子网划分
将192.168.1.0/24划分为:
- 2个相等的子网
- 4个相等的子网
- 8个相等的子网
练习3:实际应用
一个公司有以下需求:
- 部门A:需要50台主机
- 部门B:需要30台主机
- 部门C:需要20台主机
给定192.168.0.0/24,如何划分?
练习4:进阶题目
如何判断两个IP是否在同一子网?
- IP1: 192.168.1.100/25
- IP2: 192.168.1.150/25
💡 今日金句:子网划分是网络规划的基本功!
👉 上一天:IP地址详解 | 返回目录 | 下一天:MAC地址和ARP