fix bug scan ip

This commit is contained in:
2026-03-10 18:55:03 +07:00
parent adf7253350
commit 627197e29e
2 changed files with 22 additions and 6 deletions

View File

@@ -1,23 +1,31 @@
import subprocess import subprocess
import sys import sys
import ipaddress import ipaddress
import threading
from concurrent.futures import ThreadPoolExecutor, as_completed from concurrent.futures import ThreadPoolExecutor, as_completed
# Windows: prevent subprocess from opening visible console windows # Windows: prevent subprocess from opening visible console windows
_NO_WINDOW = subprocess.CREATE_NO_WINDOW if sys.platform == "win32" else 0 _NO_WINDOW = subprocess.CREATE_NO_WINDOW if sys.platform == "win32" else 0
# Concurrent ping workers per platform
_MAX_WORKERS_WIN = 50
_MAX_WORKERS_OTHER = 64
def _ping_one(ip, is_win): def _ping_one(ip, is_win):
"""Ping a single IP. Returns True if host responds.""" """Ping a single IP. Returns True if host responds."""
try: try:
if is_win: if is_win:
# Capture stdout to check for TTL= — more reliable than returncode
# on Windows (returncode can be 0 even for "Destination unreachable")
r = subprocess.run( r = subprocess.run(
["ping", "-n", "1", "-w", "500", str(ip)], ["ping", "-n", "1", "-w", "500", str(ip)],
stdout=subprocess.DEVNULL, stdout=subprocess.PIPE,
stderr=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
timeout=3, timeout=3,
creationflags=_NO_WINDOW creationflags=_NO_WINDOW
) )
return r.returncode == 0 and b"TTL=" in r.stdout
elif sys.platform == "darwin": elif sys.platform == "darwin":
r = subprocess.run( r = subprocess.run(
["ping", "-c", "1", "-W", "300", str(ip)], ["ping", "-c", "1", "-W", "300", str(ip)],
@@ -49,17 +57,22 @@ def _ping_sweep(network, progress_cb=None):
is_win = sys.platform == "win32" is_win = sys.platform == "win32"
hosts = list(net.hosts()) hosts = list(net.hosts())
total = len(hosts) total = len(hosts)
workers = min(_MAX_WORKERS_WIN if is_win else _MAX_WORKERS_OTHER, len(hosts))
done_count = [0] done_count = [0]
lock = threading.Lock()
alive = [] alive = []
def _ping_and_track(ip): def _ping_and_track(ip):
ok = _ping_one(ip, is_win) ok = _ping_one(ip, is_win)
with lock:
done_count[0] += 1 done_count[0] += 1
current = done_count[0]
if progress_cb: if progress_cb:
progress_cb(done_count[0], total) progress_cb(current, total)
return (str(ip), ok) return (str(ip), ok)
with ThreadPoolExecutor(max_workers=min(64, len(hosts))) as executor: with ThreadPoolExecutor(max_workers=workers) as executor:
futures = [executor.submit(_ping_and_track, ip) for ip in hosts] futures = [executor.submit(_ping_and_track, ip) for ip in hosts]
for f in as_completed(futures): for f in as_completed(futures):
ip_str, ok = f.result() ip_str, ok = f.result()

View File

@@ -457,11 +457,14 @@ class App(QWidget):
lbl.setStyleSheet("color: #cdd6f4; font-weight: bold;") lbl.setStyleSheet("color: #cdd6f4; font-weight: bold;")
return lbl return lbl
# IPs permanently hidden from the device list (never shown in UI)
_HIDDEN_IPS = {"192.168.11.102"}
def _get_filtered_devices(self): def _get_filtered_devices(self):
"""Return devices filtered based on show_all checkbox.""" """Return devices filtered based on show_all checkbox."""
if self.show_all_cb.isChecked(): if self.show_all_cb.isChecked():
return list(self.all_devices) return [d for d in self.all_devices if d["ip"] not in self._HIDDEN_IPS]
excluded = {self.local_ip, self.gateway_ip} excluded = {self.local_ip, self.gateway_ip} | self._HIDDEN_IPS
return [d for d in self.all_devices if d["ip"] not in excluded] return [d for d in self.all_devices if d["ip"] not in excluded]
def _refresh_table(self): def _refresh_table(self):