子網掩碼計算器:Python + Tkinter 實現
- 引言
- 代碼功能概述
- 代碼實現思路
- 1. 界面設計
- 2. 功能實現
- 3. 事件處理
- 子網掩碼計算器實現步驟
- 1. 導入必要的庫
- 2. 定義主窗口類 SubnetCalculatorApp
- 3. 創建菜單欄
- 4. 創建界面組件
- 5. 判斷 IP 地址類別
- 6. 計算子網信息
- 7. 其他功能函數
- 代碼運行效果
- 總結
引言
在網絡工程和網絡管理領域,子網掩碼的計算是一項基礎且重要的工作。通過子網掩碼,我們可以將一個大的網絡劃分為多個小的子網,從而提高網絡的安全性和可管理性。今天,我們將介紹一個使用 Python 和 Tkinter 庫實現的子網掩碼計算器,它可以幫助我們快速計算子網信息,并且支持歷史記錄的查看和導出。
代碼功能概述
這個子網掩碼計算器具有以下主要功能:
- 輸入驗證:驗證用戶輸入的 IP 地址和子網掩碼 / CIDR 是否有效。
- 子網計算:根據輸入的 IP 地址和子網掩碼 / CIDR 計算網絡地址、廣播地址、可用 IP 數、可用 IP 范圍等信息。
- IP 地址分類:判斷輸入的 IP 地址屬于 A、B、C、D、E 類中的哪一類,以及是公網地址還是私有地址。
- 結果顯示:將計算結果顯示在界面上,并支持復制結果到剪貼板。
- 歷史記錄:保存最近 5 條計算結果,并支持查看和導出歷史記錄。
代碼實現思路
1. 界面設計
- 使用 Tkinter 庫創建一個圖形用戶界面(GUI),包括輸入框、按鈕、標簽和表格等組件。
- 通過布局管理器(如 pack 和 grid)將這些組件排列在合適的位置。
2. 功能實現
- 輸入驗證:編寫函數
validate_ip
和validate_mask
來驗證 IP 地址和子網掩碼的格式是否正確。 - 子網計算:
- 編寫函數
ip_to_int
和int_to_ip
來實現 IP 地址和 32 位整數之間的轉換。 - 根據子網掩碼計算網絡地址、廣播地址等信息。
- 編寫函數
- IP 地址分類:編寫函數
get_ip_class
來判斷 IP 地址的類別。 - 歷史記錄管理:
- 使用列表
self.history
來存儲最近 5 條計算結果。 - 提供查看和導出歷史記錄的功能。
- 使用列表
3. 事件處理
- 為每個按鈕綁定相應的事件處理函數,例如:
- 點擊 “計算” 按鈕時調用
calculate
函數進行子網計算。 - 點擊 “保存當前結果” 按鈕時調用
save_current_result
函數保存結果。
- 點擊 “計算” 按鈕時調用
子網掩碼計算器實現步驟
1. 導入必要的庫
import tkinter as tk
from tkinter import ttk, messagebox, filedialog
import csv
from datetime import datetime
這里導入了 Tkinter 庫用于創建 GUI,csv 庫用于處理 CSV 文件,datetime 庫用于記錄時間。
2. 定義主窗口類 SubnetCalculatorApp
class SubnetCalculatorApp(tk.Tk):def __init__(self):super().__init__()self.title("子網掩碼計算器")self.geometry("650x470") # 調整窗口大小self.resizable(False, False)self.history = [] # 存儲最近5條歷史記錄self.create_widgets()self.create_menu()
在 init 方法中,我們初始化了主窗口的標題、大小、是否可調整大小屬性,并創建了一個空的歷史記錄列表。然后,我們調用了 create_widgets 和 create_menu 方法來創建界面組件和菜單欄。
3. 創建菜單欄
def create_menu(self):"""創建菜單欄"""menubar = tk.Menu(self)# 歷史記錄菜單history_menu = tk.Menu(menubar, tearoff=0)history_menu.add_command(label="查看歷史記錄", command=self.show_history)history_menu.add_command(label="導出歷史記錄...", command=self.export_history)menubar.add_cascade(label="歷史記錄", menu=history_menu)self.config(menu=menubar)
在 create_menu 方法中,我們創建了一個菜單欄,并為其添加了一個名為“歷史記錄”的子菜單。該子菜單包含兩個選項:“查看歷史記錄”和“導出歷史記錄…”。當用戶點擊這些選項時,將分別調用 show_history 和 export_history 方法。最后,我們將菜單欄設置到主窗口中。
4. 創建界面組件
def create_widgets(self):"""創建界面組件"""# 輸入區域input_frame = ttk.Frame(self)input_frame.pack(padx=10, pady=10, fill=tk.X)ttk.Label(input_frame, text="IP地址:").grid(row=0, column=0, sticky=tk.W)self.ip_entry = ttk.Entry(input_frame, width=20)self.ip_entry.grid(row=0, column=1, padx=5)ttk.Label(input_frame, text="子網掩碼/CIDR:").grid(row=1, column=0, sticky=tk.W)self.mask_entry = ttk.Entry(input_frame, width=20)self.mask_entry.grid(row=1, column=1, padx=5)ttk.Button(input_frame, text="計算", command=self.calculate).grid(row=2, column=0, columnspan=2, pady=10)# 結果區域result_frame = ttk.LabelFrame(self, text="計算結果")result_frame.pack(padx=10, pady=5, fill=tk.BOTH, expand=True)result_labels = [("網絡地址:", "network"),("廣播地址:", "broadcast"),("可用IP數:", "hosts"),("可用IP范圍:", "range"),("CIDR表示:", "cidr"),("子網掩碼:", "mask"),("IP版本:", "version"),("網絡類別:", "class") # 新增網絡類別]for i, (label, _) in enumerate(result_labels):ttk.Label(result_frame, text=label).grid(row=i, column=0, sticky=tk.W, padx=5, pady=2)setattr(self, f"result_{label.split(':')[0]}", ttk.Label(result_frame, text=""))getattr(self, f"result_{label.split(':')[0]}").grid(row=i, column=1, sticky=tk.W, padx=5, pady=2)# 按鈕區域button_frame = ttk.Frame(self)button_frame.pack(pady=5)ttk.Button(button_frame, text="保存當前結果", command=self.save_current_result).pack(side=tk.LEFT, padx=5)ttk.Button(button_frame, text="復制結果", command=self.copy_results).pack(side=tk.LEFT, padx=5)ttk.Button(button_frame, text="清除輸入", command=self.clear_inputs).pack(side=tk.LEFT, padx=5)
這段代碼創建了輸入區域、結果區域和按鈕區域,并為每個組件設置了相應的布局和事件處理函數。
5. 判斷 IP 地址類別
def get_ip_class(self, ip_str):"""判斷IP地址類別"""first_octet = int(ip_str.split('.')[0])if 1 <= first_octet <= 126:return "A類(公網地址)" if first_octet != 10 else "A類(私有地址)"elif 128 <= first_octet <= 191:if first_octet == 172 and 16 <= int(ip_str.split('.')[1]) <= 31:return "B類(私有地址)"return "B類(公網地址)"elif 192 <= first_octet <= 223:if first_octet == 192 and int(ip_str.split('.')[1]) == 168:return "C類(私有地址)"return "C類(公網地址)"elif 224 <= first_octet <= 239:return "D類(組播地址)"elif 240 <= first_octet <= 255:return "E類(保留地址)"elif first_octet == 127:return "環回地址"return "未知類別"
這個函數根據 IP 地址的第一個八位組判斷其類別,并區分公網地址和私有地址。
6. 計算子網信息
def calculate(self):"""計算子網信息"""try:ip_str = self.ip_entry.get().strip()mask_str = self.mask_entry.get().strip().lstrip('/')if not self.validate_ip(ip_str):raise ValueError("無效的IP地址格式")# 獲取網絡類別ip_class = self.get_ip_class(ip_str)ip_int = self.ip_to_int(ip_str)mask_int, cidr = self.parse_mask(mask_str, ip_int)subnet_mask = self.int_to_ip(mask_int)network_int = ip_int & mask_intbroadcast_int = network_int | (~mask_int & 0xFFFFFFFF)hosts_count = max(broadcast_int - network_int - 1, 0)# 更新結果self.result_網絡地址.config(text=self.int_to_ip(network_int))self.result_廣播地址.config(text=self.int_to_ip(broadcast_int))self.result_可用IP數.config(text=f"{hosts_count} 個")self.result_CIDR表示.config(text=f"/{cidr}")self.result_子網掩碼.config(text=subnet_mask)self.result_IP版本.config(text="IPv4")self.result_網絡類別.config(text=ip_class) # 顯示網絡類別if hosts_count > 0:first_ip = self.int_to_ip(network_int + 1)last_ip = self.int_to_ip(broadcast_int - 1)self.result_可用IP范圍.config(text=f"{first_ip} - {last_ip}")else:self.result_可用IP范圍.config(text="無可用IP")except Exception as e:messagebox.showerror("錯誤", str(e))
在 calculate 函數中,首先驗證輸入的 IP 地址和子網掩碼 / CIDR 是否有效,然后進行子網計算,并將結果顯示在界面上。
7. 其他功能函數
代碼中還包含了清空輸入框、復制結果、保存當前結果、查看歷史記錄和導出歷史記錄等功能函數,這些函數的實現邏輯都比較簡單,這里就不再詳細介紹了。
代碼運行效果
運行代碼后,會彈出一個子網掩碼計算器的窗口,界面如下:
用戶可以在輸入框中輸入 IP 地址和子網掩碼 / CIDR,點擊 “計算” 按鈕即可得到計算結果。點擊 “保存當前結果” 按鈕可以將結果保存到 CSV 文件中,點擊 “復制結果” 按鈕可以將結果復制到剪貼板。通過菜單欄中的 “歷史記錄” 菜單可以查看和導出最近 5 條計算結果。
總結
通過這個子網掩碼計算器的實現,我們學習了如何使用 Python 和 Tkinter 庫創建一個簡單的 GUI 應用程序。同時,我們也掌握了子網計算的基本原理和 IP 地址分類的方法。希望這篇博客對你有所幫助,如果你有任何問題或建議,歡迎在評論區留言。