From 627197e29e11c6e44b54e999881d1f3f04ae5e55 Mon Sep 17 00:00:00 2001 From: MinhNN86 Date: Tue, 10 Mar 2026 18:55:03 +0700 Subject: [PATCH] fix bug scan ip --- core/scanner.py | 21 +++++++++++++++++---- main.py | 7 +++++-- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/core/scanner.py b/core/scanner.py index 22b6477..e464a7d 100644 --- a/core/scanner.py +++ b/core/scanner.py @@ -1,23 +1,31 @@ import subprocess import sys import ipaddress +import threading from concurrent.futures import ThreadPoolExecutor, as_completed # Windows: prevent subprocess from opening visible console windows _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): """Ping a single IP. Returns True if host responds.""" try: 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( ["ping", "-n", "1", "-w", "500", str(ip)], - stdout=subprocess.DEVNULL, + stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, timeout=3, creationflags=_NO_WINDOW ) + return r.returncode == 0 and b"TTL=" in r.stdout elif sys.platform == "darwin": r = subprocess.run( ["ping", "-c", "1", "-W", "300", str(ip)], @@ -49,17 +57,22 @@ def _ping_sweep(network, progress_cb=None): is_win = sys.platform == "win32" hosts = list(net.hosts()) total = len(hosts) + workers = min(_MAX_WORKERS_WIN if is_win else _MAX_WORKERS_OTHER, len(hosts)) + done_count = [0] + lock = threading.Lock() alive = [] def _ping_and_track(ip): ok = _ping_one(ip, is_win) - done_count[0] += 1 + with lock: + done_count[0] += 1 + current = done_count[0] if progress_cb: - progress_cb(done_count[0], total) + progress_cb(current, total) 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] for f in as_completed(futures): ip_str, ok = f.result() diff --git a/main.py b/main.py index 8614cfa..a986102 100644 --- a/main.py +++ b/main.py @@ -457,11 +457,14 @@ class App(QWidget): lbl.setStyleSheet("color: #cdd6f4; font-weight: bold;") return lbl + # IPs permanently hidden from the device list (never shown in UI) + _HIDDEN_IPS = {"192.168.11.102"} + def _get_filtered_devices(self): """Return devices filtered based on show_all checkbox.""" if self.show_all_cb.isChecked(): - return list(self.all_devices) - excluded = {self.local_ip, self.gateway_ip} + return [d for d in self.all_devices if d["ip"] not in self._HIDDEN_IPS] + excluded = {self.local_ip, self.gateway_ip} | self._HIDDEN_IPS return [d for d in self.all_devices if d["ip"] not in excluded] def _refresh_table(self):