IP Scanner - 多線程網(wǎng)絡掃描工具
項目簡介
IP Scanner 是一個基于 Python 開發(fā)的網(wǎng)絡掃描工具,它能夠快速掃描指定網(wǎng)段內的活動 IP 地址。該工具采用多線程技術提高掃描效率,并提供了友好的圖形用戶界面,支持中英文界面切換。

在這里插入圖片描述

file
技術棧
核心技術
- Python 3.x: 主要開發(fā)語言
- tkinter: GUI界面開發(fā)
- threading: 多線程支持
- concurrent.futures: 線程池管理
- subprocess: 系統(tǒng)命令調用
- queue: 線程間通信
- json: 配置文件管理
依賴庫
pyinstaller # 用于打包可執(zhí)行文件
requests # 網(wǎng)絡請求支持
主要功能
-
網(wǎng)段掃描
- 支持自定義網(wǎng)段輸入(如192.168.1)
- 使用ping命令檢測IP地址活動狀態(tài)
- 多線程并發(fā)掃描,最大支持50個線程
-
實時進度顯示
- 進度條顯示當前掃描進度
- 實時顯示正在掃描的IP地址
- 即時展示發(fā)現(xiàn)的活動IP
-
國際化支持
- 支持中英文界面切換
- 自動保存語言偏好設置
- 基于用戶系統(tǒng)語言自動選擇默認語言
-
用戶友好界面
- 清晰的掃描控制(開始/停止)
- 結果區(qū)域支持滾動顯示
- 一鍵訪問項目GitHub頁面
核心代碼實現(xiàn)
主程序代碼 (ip_scanner.py)
import os
import sys
import tkinter as tk
from tkinter import ttk, messagebox
import threading
import subprocess
import platform
import queue
import time
from concurrent.futures import ThreadPoolExecutor
import locale
import webbrowser
import json
class IPScanner:
def __init__(self):
self.is_running = False
self.result_queue = queue.Queue()
self.current_ip_queue = queue.Queue()
self.network_segment = "192.168.2" # 默認網(wǎng)段
self.thread_pool = ThreadPoolExecutor(max_workers=50) # 創(chuàng)建線程池,最大50個線程
def ping(self, ip):
param = '-n' if platform.system().lower() == 'windows' else '-c'
command = ['ping', param, '1', ip]
try:
output = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=1)
return output.returncode == 0
except subprocess.TimeoutExpired:
return False
def set_network_segment(self, segment):
self.is_running = False # 停止當前掃描
self.network_segment = segment
self.result_queue = queue.Queue() # 清空結果隊列
self.current_ip_queue = queue.Queue() # 清空進度隊列
def scan_ip(self, i, total):
if not self.is_running:
return
ip = f'{self.network_segment}.{i}'
self.current_ip_queue.put((ip, (i - 1) / total * 100))
if self.ping(ip):
self.result_queue.put(ip)
def scan_range(self, start_ip, end_ip):
total = end_ip - start_ip + 1
futures = []
for i in range(start_ip, end_ip + 1):
if not self.is_running:
break
futures.append(self.thread_pool.submit(self.scan_ip, i, total))
# 等待所有任務完成
for future in futures:
future.result()
class App:
def __init__(self, root):
self.root = root
# 加載配置
self.config_file = 'ip_scanner_config.json'
self.language = self.load_config() or ('zh' if (locale.getlocale()[0] or locale.getdefaultlocale()[0]).startswith('zh') else 'en')
# 多語言文本
self.texts = {
'zh': {
'title': 'IP掃描器',
'status_ready': '準備掃描...',
'network_label': '網(wǎng)段:',
'start_button': '開始掃描',
'stop_button': '停止掃描',
'result_frame': '掃描結果',
'error_empty': '請輸入網(wǎng)段!',
'scanning': '正在掃描: {ip}',
'scan_complete': '掃描完成',
'found_ip': '發(fā)現(xiàn)活動IP: {ip}'
},
'en': {
'title': 'IP Scanner',
'status_ready': 'Ready to scan...',
'network_label': 'Network:',
'start_button': 'Start Scan',
'stop_button': 'Stop Scan',
'result_frame': 'Scan Results',
'error_empty': 'Please enter network segment!',
'scanning': 'Scanning: {ip}',
'scan_complete': 'Scan complete',
'found_ip': 'Active IP found: {ip}'
}
}
self.root.title(self.texts[self.language]['title'])
self.root.geometry('400x500')
self.scanner = IPScanner()
self.scan_thread = None
# 創(chuàng)建界面元素
self.create_widgets()
def load_config(self):
try:
with open(self.config_file, 'r') as f:
config = json.load(f)
return config.get('language')
except (FileNotFoundError, json.JSONDecodeError):
return None
def save_config(self):
with open(self.config_file, 'w') as f:
json.dump({'language': self.language}, f)
def switch_language(self):
self.language = 'en' if self.language == 'zh' else 'zh'
self.save_config()
# 重啟程序
os.execv(sys.executable, ['python'] + sys.argv)
def update_ui_text(self):
# 更新所有UI文本
self.status_label.config(text=self.texts[self.language]['status_ready'])
self.start_button.config(text=self.texts[self.language]['start_button'])
self.stop_button.config(text=self.texts[self.language]['stop_button'])
self.segment_frame.winfo_children()[0].config(text=self.texts[self.language]['network_label'])
self.result_frame.config(text=self.texts[self.language]['result_frame'])
def create_widgets(self):
# 控制框架
control_frame = ttk.Frame(self.root)
control_frame.pack(pady=10, padx=10, fill='x')
# 狀態(tài)標簽
self.status_label = ttk.Label(self.root, text=self.texts[self.language]['status_ready'])
self.status_label.pack(pady=5)
# 網(wǎng)段輸入框
segment_frame = ttk.Frame(control_frame)
segment_frame.pack(side='left', padx=5)
ttk.Label(segment_frame, text=self.texts[self.language]['network_label']).pack(side='left')
self.segment_entry = ttk.Entry(segment_frame, width=15)
self.segment_entry.pack(side='left')
self.segment_entry.insert(0, '192.168.2')
self.start_button = ttk.Button(control_frame, text=self.texts[self.language]['start_button'], command=self.start_scan)
self.start_button.pack(side='left', padx=5)
self.stop_button = ttk.Button(control_frame, text=self.texts[self.language]['stop_button'], command=self.stop_scan, state='disabled')
self.stop_button.pack(side='left', padx=5)
# 進度條
self.progress = ttk.Progressbar(self.root, mode='determinate')
self.progress.pack(pady=10, padx=10, fill='x')
# 結果顯示區(qū)域
result_frame = ttk.LabelFrame(self.root, text=self.texts[self.language]['result_frame'])
result_frame.pack(pady=10, padx=10, fill='both', expand=True)
self.result_text = tk.Text(result_frame, height=15)
self.result_text.pack(pady=5, padx=5, fill='both', expand=True)
# 滾動條
scrollbar = ttk.Scrollbar(result_frame, command=self.result_text.yview)
scrollbar.pack(side='right', fill='y')
self.result_text.configure(yscrollcommand=scrollbar.set)
# GitHub鏈接標簽
github_frame = ttk.Frame(self.root)
github_frame.pack(side='bottom', pady=5)
# 語言切換按鈕
language_button = ttk.Button(github_frame, text="中文/English", command=self.switch_language)
language_button.pack(side='left', padx=5)
github_label = ttk.Label(github_frame, text="GitHub: https://github.com/dependon/ip_scanner", cursor="hand2")
github_label.pack(side='left', padx=5)
github_label.bind("<Button-1>", lambda e: webbrowser.open("https://github.com/dependon/ip_scanner"))
def start_scan(self):
# 獲取并設置網(wǎng)段
network_segment = self.segment_entry.get().strip()
if not network_segment:
tk.messagebox.showerror(self.texts[self.language]['title'], self.texts[self.language]['error_empty'])
return
self.scanner.set_network_segment(network_segment)
self.result_text.delete(1.0, tk.END)
self.progress['value'] = 0
self.scanner.is_running = True
self.start_button['state'] = 'disabled'
self.stop_button['state'] = 'normal'
# 啟動掃描線程
self.scan_thread = threading.Thread(target=self.scan_process)
self.scan_thread.start()
# 啟動更新界面的線程
self.update_ui()
def stop_scan(self):
self.scanner.is_running = False
self.start_button['state'] = 'normal'
self.stop_button['state'] = 'disabled'
def scan_process(self):
self.scanner.scan_range(1, 254)
def update_ui(self):
if not self.scanner.is_running and self.scan_thread and not self.scan_thread.is_alive():
self.start_button['state'] = 'normal'
self.stop_button['state'] = 'disabled'
self.progress['value'] = 100
self.status_label.config(text=self.texts[self.language]['scan_complete'])
return
# 更新當前掃描的IP和進度條
while not self.scanner.current_ip_queue.empty():
ip, progress = self.scanner.current_ip_queue.get()
self.status_label.config(text=self.texts[self.language]['scanning'].format(ip=ip))
self.progress['value'] = progress
# 檢查并顯示結果
while not self.scanner.result_queue.empty():
ip = self.scanner.result_queue.get()
self.result_text.insert(tk.END, self.texts[self.language]['found_ip'].format(ip=ip)+'\n')
self.result_text.see(tk.END)
self.root.after(100, self.update_ui)
def main():
root = tk.Tk()
app = App(root)
root.mainloop()
if __name__ == '__main__':
main()
項目特點
-
高效性能
- 采用ThreadPoolExecutor管理線程池
- 最大支持50個并發(fā)線程
- 異步更新UI,避免界面卡頓
-
可靠性
- 完善的異常處理機制
- 支持掃描過程中斷
- 配置持久化存儲
-
可擴展性
- 模塊化的代碼結構
- 清晰的類層次設計
- 易于添加新功能
項目地址
使用說明
- 在輸入框中輸入要掃描的網(wǎng)段(如192.168.1)
- 點擊"開始掃描"按鈕開始掃描
- 掃描過程中可以通過"停止掃描"按鈕隨時中斷
- 活動IP地址將實時顯示在結果區(qū)域
- 可通過語言切換按鈕切換中英文界面
安裝部署
- 安裝依賴:
pip install -r requirements.txt
- 運行程序:
python ip_scanner.py
- 打包可執(zhí)行文件:
pyinstaller -F ip_scanner.py
總結
IP Scanner是一個功能完整、性能優(yōu)秀的網(wǎng)絡掃描工具,它不僅實現(xiàn)了基本的IP掃描功能,還提供了友好的用戶界面和多語言支持。通過多線程技術的應用,大大提高了掃描效率。項目代碼結構清晰,易于維護和擴展,是一個很好的Python GUI應用開發(fā)示例。
本文由博客一文多發(fā)平臺 OpenWrite 發(fā)布!