[Python] 纯文本查看 复制代码
import tkinter as tk
from tkinter import ttk, messagebox
import ipaddress
# VLSM 计算函数
def calculate_vlsm(ip_network_str, subnet_requirements_str):
try:
# 解析初始网络
ip_network = ipaddress.ip_network(ip_network_str, strict=False)
# 解析子网需求
subnet_requirements = [int(req) for req in subnet_requirements_str.split(',')]
subnet_requirements = [(chr(65 + i), req) for i, req in enumerate(subnet_requirements)]
# 按主机数量从大到小排序子网需求
subnet_requirements.sort(key=lambda x: x[1], reverse=True)
results = []
current_network = ip_network
for name, hosts in subnet_requirements:
# 计算满足主机数量所需的前缀长度
required_hosts = hosts + 2 # 加上网络地址和广播地址
prefix_length = 32 - (required_hosts - 1).bit_length()
# 获取当前子网
subnet = list(current_network.subnets(new_prefix=prefix_length))[0]
# 添加结果
results.append((name, subnet))
# 更新剩余网络
remaining_networks = list(current_network.address_exclude(subnet))
if not remaining_networks:
break
current_network = remaining_networks[0]
return results, ip_network
except Exception as e:
messagebox.showerror("错误", str(e))
return None, None
# 更新输出
def update_output():
ip_network_str = ip_entry.get().strip()
subnet_requirements_str = subnet_requirements_entry.get().strip()
results, ip_network = calculate_vlsm(ip_network_str, subnet_requirements_str)
if results is None:
return
# 清空输出
output_textbox.delete("1.0", tk.END)
# 输出基础网络信息
output_textbox.insert(tk.END, f"基础网络:{ip_network}\n\n")
# 输出子网划分详细信息
for i, (name, subnet) in enumerate(results, start=1):
display_subnet_info(subnet, name, i)
# 初始状态为十进制显示
global display_mode
display_mode = "decimal"
toggle_button.config(text="二进制显示")
# 切换显示模式
def toggle_display_mode():
global display_mode
if display_mode == "decimal":
display_mode = "binary"
toggle_button.config(text="十进制显示")
show_binary_info()
else:
display_mode = "decimal"
toggle_button.config(text="二进制显示")
update_output()
# 显示子网信息
def display_subnet_info(subnet, name, index):
# IP地址范围
ip_range = f"{subnet.network_address} - {subnet.broadcast_address}"
# 可用IP地址范围
usable_ip_range = list(subnet.hosts())
first_usable = usable_ip_range[0] if usable_ip_range else ""
last_usable = usable_ip_range[-1] if usable_ip_range else ""
# 网络地址
network_addr = subnet.network_address
# 广播地址
broadcast_addr = subnet.broadcast_address
# 子网掩码
subnet_mask = subnet.netmask
# 可用地址数
num_addresses = subnet.num_addresses - 2
# 分行展示每个子网的详细信息
output_textbox.insert(tk.END, f"子网序号:{index}\n")
output_textbox.insert(tk.END, f"子网名称:{name}\n")
output_textbox.insert(tk.END, f"网络地址:{subnet}\n")
output_textbox.insert(tk.END, f"子网掩码:{subnet_mask}\n")
output_textbox.insert(tk.END, f"可用地址数:{num_addresses}\n")
output_textbox.insert(tk.END, f"起始地址:{first_usable}\n")
output_textbox.insert(tk.END, f"结束地址:{last_usable}\n")
output_textbox.insert(tk.END, f"广播地址:{broadcast_addr}\n\n")
# 显示二进制信息
def show_binary_info():
# 获取当前输出内容
current_output = output_textbox.get("1.0", tk.END)
# 清空输出
output_textbox.delete("1.0", tk.END)
# 重新插入基础网络信息
ip_network_str = ip_entry.get().strip()
ip_network = ipaddress.ip_network(ip_network_str, strict=False)
output_textbox.insert(tk.END, f"基础网络:{ip_network}\n\n")
# 重新插入子网划分详细信息并添加二进制信息
results, _ = calculate_vlsm(ip_network_str, subnet_requirements_entry.get().strip())
for i, (name, subnet) in enumerate(results, start=1):
display_subnet_info(subnet, name, i)
# 添加二进制信息
output_textbox.insert(tk.END, f"网络地址(二进制):{'.'.join(format(int(octet), '08b') for octet in str(subnet).split('/')[0].split('.'))}\n")
output_textbox.insert(tk.END, f"子网掩码(二进制):{'.'.join(format(int(octet), '08b') for octet in str(subnet.netmask).split('.'))}\n\n")
# 创建主窗口
root = tk.Tk()
root.title("VLSM 计算器")
# 主标题
title_label = ttk.Label(root, text="VLSM计算器", font=("Helvetica", 18, "bold"))
title_label.pack(pady=10)
# 输入区域
input_frame = ttk.Frame(root)
input_frame.pack(padx=10, pady=10, fill=tk.X)
# 输入 IP 网络
ip_label = ttk.Label(input_frame, text="输入初始网络(例如:192.168.1.0/24):")
ip_label.grid(row=0, column=0, padx=5, pady=5, sticky="w")
ip_entry = ttk.Entry(input_frame, width=30)
ip_entry.insert(0, "192.168.1.0/24") # 默认内容
ip_entry.grid(row=0, column=1, padx=5, pady=5, sticky="ew")
# 输入子网需求
subnet_requirements_label = ttk.Label(input_frame, text="每个子网所需主机数(用逗号分隔,例如:50,20,10):")
subnet_requirements_label.grid(row=1, column=0, padx=5, pady=5, sticky="w")
subnet_requirements_entry = ttk.Entry(input_frame, width=30)
subnet_requirements_entry.insert(0, "3,13,35,20,5") # 默认内容
subnet_requirements_entry.grid(row=1, column=1, padx=5, pady=5, sticky="ew")
# 计算按钮
calculate_button = ttk.Button(input_frame, text="计算子网划分", command=update_output)
calculate_button.grid(row=2, column=0, padx=5, pady=10)
# 二进制显示按钮
toggle_button = ttk.Button(input_frame, text="二进制显示", command=toggle_display_mode)
toggle_button.grid(row=2, column=1, padx=5, pady=10)
# 输出区域
output_frame = ttk.Frame(root)
output_frame.pack(padx=10, pady=10, fill=tk.BOTH, expand=True)
# 输出文本框
output_textbox = tk.Text(output_frame, height=15, width=60)
output_textbox.pack(fill=tk.BOTH, expand=True)
# 在输出区域的文本框里显示默认内容
output_textbox.insert(tk.END, "程序说明:\n\n工具简介:\n这是一个VLSM(可变长度子网掩码)计算器,能够帮助网络管理员快速计算和规划IPv4网络的子网划分,支持自定义主机数需求,自动计算最优子网分配方案,并提供完整的子网信息包括网络地址、子网掩码、可用地址范围和广播地址。\n\n使用方法:\n在第一个输入框中输入基础网络地址(如192.168.1.0/24),在第二个输入框中输入每个子网所需的主机数并用英文逗号分隔(如50,20,10),点击计算子网划分按钮即可获得详细的VLSM子网划分结果。")
# 全局变量
display_mode = "decimal"
# 运行主循环
root.mainloop()