12
This commit is contained in:
Binary file not shown.
Binary file not shown.
+32
-27
@@ -4,23 +4,22 @@ import subprocess
|
|||||||
import concurrent.futures
|
import concurrent.futures
|
||||||
import threading
|
import threading
|
||||||
import re
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
class PingFun:
|
class PingFun:
|
||||||
def __init__(self, result_box: scrolledtext.ScrolledText):
|
def __init__(self, result_box: scrolledtext.ScrolledText):
|
||||||
self.result_box = result_box
|
self.result_box = result_box
|
||||||
|
|
||||||
# Ping 状态和统计
|
# Ping 状态和统计
|
||||||
self.process = None # 子进程对象
|
self.process = None
|
||||||
self.stop_flag = False # 停止标志
|
self.stop_flag = False
|
||||||
self.sent = 0 # 发送的包数
|
self.sent = 0
|
||||||
self.received = 0 # 接收的包数
|
self.received = 0
|
||||||
self.rtts = [] # 存储延迟值
|
self.rtts = []
|
||||||
|
|
||||||
def strat_ping(self, host, local_ip=None, callback=None):
|
def strat_ping(self, host, local_ip=None, callback=None):
|
||||||
"""开始 ping"""
|
"""开始 ping"""
|
||||||
self.callback = callback
|
self.callback = callback
|
||||||
|
|
||||||
# 清空显示框和统计数据
|
|
||||||
self.result_box.delete('1.0', tk.END)
|
self.result_box.delete('1.0', tk.END)
|
||||||
self.sent = 0
|
self.sent = 0
|
||||||
self.received = 0
|
self.received = 0
|
||||||
@@ -36,17 +35,26 @@ class PingFun:
|
|||||||
def stop_ping(self):
|
def stop_ping(self):
|
||||||
"""手动停止 ping"""
|
"""手动停止 ping"""
|
||||||
if self.process:
|
if self.process:
|
||||||
self.process.terminate() # 立即终止子进程
|
self.process.terminate()
|
||||||
self.result_box.insert(tk.END, "\nPing 已手动停止。\n")
|
self.result_box.insert(tk.END, "\nPing 已手动停止。\n")
|
||||||
self.result_box.see(tk.END)
|
self.result_box.see(tk.END)
|
||||||
self.process = None
|
self.process = None
|
||||||
self.show_statistics()
|
self.show_statistics()
|
||||||
|
|
||||||
def ping(self, command):
|
def ping(self, command):
|
||||||
"""执行 ping 命令并处理输出"""
|
"""执行 ping 命令并处理输出"""
|
||||||
rtt_pattern = re.compile(r'时间[=<](\d+)ms', re.IGNORECASE)
|
rtt_pattern = re.compile(r'时间[=<](\d+)ms', re.IGNORECASE)
|
||||||
try:
|
try:
|
||||||
self.process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True)
|
# 👇关键:隐藏 CMD 窗口
|
||||||
|
creationflags = subprocess.CREATE_NO_WINDOW if sys.platform.startswith("win") else 0
|
||||||
|
|
||||||
|
self.process = subprocess.Popen(
|
||||||
|
command,
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.STDOUT,
|
||||||
|
universal_newlines=True,
|
||||||
|
creationflags=creationflags # ✅ 加上这个!
|
||||||
|
)
|
||||||
for line in iter(self.process.stdout.readline, ''):
|
for line in iter(self.process.stdout.readline, ''):
|
||||||
if self.stop_flag:
|
if self.stop_flag:
|
||||||
break
|
break
|
||||||
@@ -54,7 +62,6 @@ class PingFun:
|
|||||||
self.result_box.insert(tk.END, line)
|
self.result_box.insert(tk.END, line)
|
||||||
self.result_box.see(tk.END)
|
self.result_box.see(tk.END)
|
||||||
self.sent += 1
|
self.sent += 1
|
||||||
# 解析延迟
|
|
||||||
match = rtt_pattern.search(line)
|
match = rtt_pattern.search(line)
|
||||||
if match:
|
if match:
|
||||||
self.received += 1
|
self.received += 1
|
||||||
@@ -62,13 +69,11 @@ class PingFun:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.result_box.insert(tk.END, f"Ping 失败: {e}\n")
|
self.result_box.insert(tk.END, f"Ping 失败: {e}\n")
|
||||||
finally:
|
finally:
|
||||||
# 清理进程对象
|
|
||||||
self.process = None
|
self.process = None
|
||||||
if self.callback:
|
if self.callback:
|
||||||
self.callback()
|
self.callback()
|
||||||
|
|
||||||
def show_statistics(self):
|
def show_statistics(self):
|
||||||
"""显示统计信息"""
|
|
||||||
if self.sent == 0:
|
if self.sent == 0:
|
||||||
return
|
return
|
||||||
loss = (self.sent - self.received) / self.sent * 100
|
loss = (self.sent - self.received) / self.sent * 100
|
||||||
@@ -81,16 +86,11 @@ class PingFun:
|
|||||||
|
|
||||||
# ================= 批量 Ping =================
|
# ================= 批量 Ping =================
|
||||||
def start_batch_ping(self, net_prefix, start, end, local_ip=None, callback=None):
|
def start_batch_ping(self, net_prefix, start, end, local_ip=None, callback=None):
|
||||||
"""
|
|
||||||
批量 Ping 多个 IP 地址。
|
|
||||||
例如:net_prefix='192.168.1.' start=1 end=254
|
|
||||||
"""
|
|
||||||
self.callback = callback
|
self.callback = callback
|
||||||
self.stop_flag = False
|
self.stop_flag = False
|
||||||
self.result_box.delete('1.0', tk.END)
|
self.result_box.delete('1.0', tk.END)
|
||||||
self.result_box.insert(tk.END, f"开始并发 Ping:{net_prefix}{start} - {net_prefix}{end}\n\n")
|
self.result_box.insert(tk.END, f"开始并发 Ping:{net_prefix}{start} - {net_prefix}{end}\n\n")
|
||||||
|
|
||||||
# ---- 启动线程池执行 ----
|
|
||||||
self.batch_thread = threading.Thread(
|
self.batch_thread = threading.Thread(
|
||||||
target=self._concurrent_batch_ping, args=(net_prefix, start, end, local_ip), daemon=True)
|
target=self._concurrent_batch_ping, args=(net_prefix, start, end, local_ip), daemon=True)
|
||||||
self.batch_thread.start()
|
self.batch_thread.start()
|
||||||
@@ -103,9 +103,20 @@ class PingFun:
|
|||||||
command = ['ping', ip, '-n', '1', '-w', '2000']
|
command = ['ping', ip, '-n', '1', '-w', '2000']
|
||||||
if local_ip:
|
if local_ip:
|
||||||
command += ['-S', local_ip]
|
command += ['-S', local_ip]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
# 👇 同样隐藏 CMD 窗口
|
||||||
text=True, timeout=2)
|
creationflags = subprocess.CREATE_NO_WINDOW if sys.platform.startswith("win") else 0
|
||||||
|
|
||||||
|
result = subprocess.run(
|
||||||
|
command,
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.PIPE,
|
||||||
|
text=True,
|
||||||
|
timeout=2,
|
||||||
|
creationflags=creationflags # ✅ 加上
|
||||||
|
)
|
||||||
|
|
||||||
if "TTL=" in result.stdout.upper():
|
if "TTL=" in result.stdout.upper():
|
||||||
return f"{ip} ✅ 通\n"
|
return f"{ip} ✅ 通\n"
|
||||||
else:
|
else:
|
||||||
@@ -116,15 +127,10 @@ class PingFun:
|
|||||||
return f"{ip} 错误: {e}\n"
|
return f"{ip} 错误: {e}\n"
|
||||||
|
|
||||||
def _concurrent_batch_ping(self, net_prefix, start, end, local_ip=None):
|
def _concurrent_batch_ping(self, net_prefix, start, end, local_ip=None):
|
||||||
"""并发执行批量 Ping"""
|
|
||||||
ip_list = [f"{net_prefix}{i}" for i in range(start, end + 1)]
|
ip_list = [f"{net_prefix}{i}" for i in range(start, end + 1)]
|
||||||
|
|
||||||
# 限制最大并发数,防止系统资源耗尽
|
|
||||||
max_workers = min(50, len(ip_list))
|
max_workers = min(50, len(ip_list))
|
||||||
|
|
||||||
with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor:
|
with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor:
|
||||||
future_to_ip = {executor.submit(self._ping_one_ip, ip, local_ip): ip for ip in ip_list}
|
future_to_ip = {executor.submit(self._ping_one_ip, ip, local_ip): ip for ip in ip_list}
|
||||||
|
|
||||||
for future in concurrent.futures.as_completed(future_to_ip):
|
for future in concurrent.futures.as_completed(future_to_ip):
|
||||||
if self.stop_flag:
|
if self.stop_flag:
|
||||||
break
|
break
|
||||||
@@ -142,10 +148,9 @@ class PingFun:
|
|||||||
self.callback()
|
self.callback()
|
||||||
|
|
||||||
def stop_batch_ping(self):
|
def stop_batch_ping(self):
|
||||||
"""停止并发批量 ping"""
|
|
||||||
if not self.batch_thread or not self.batch_thread.is_alive():
|
if not self.batch_thread or not self.batch_thread.is_alive():
|
||||||
messagebox.showinfo("提示", "当前没有正在运行的批量 Ping。")
|
messagebox.showinfo("提示", "当前没有正在运行的批量 Ping。")
|
||||||
return
|
return
|
||||||
self.stop_flag = True
|
self.stop_flag = True
|
||||||
self.result_box.insert(tk.END, "\n正在尝试停止批量 Ping...\n")
|
self.result_box.insert(tk.END, "\n正在尝试停止批量 Ping...\n")
|
||||||
self.result_box.see(tk.END)
|
self.result_box.see(tk.END)
|
||||||
|
|||||||
Reference in New Issue
Block a user