You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python端口扫描器异常重复输出:实现单次错误提示并终止程序

解决多线程端口扫描器socket.gaierror重复输出并终止程序的问题

要实现仅输出一次错误信息并立即终止所有扫描线程,你可以通过线程安全的状态标记+提前关闭线程池的方式处理:

修改后的代码示例

import socket
from concurrent.futures import ThreadPoolExecutor
import threading

# 线程安全的标志:标记是否已捕获gaierror异常
error_occurred = threading.Event()

def scan_port(host, port):
    # 如果已经发生错误,直接返回,不再执行扫描
    if error_occurred.is_set():
        return
    try:
        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
            s.settimeout(0.5)
            result = s.connect_ex((host, port))
            if result == 0:
                print(f"Port {port} is open")
    except socket.gaierror:
        # 仅当第一次触发时输出错误并终止程序
        if not error_occurred.is_set():
            error_occurred.set()
            print("错误:无法解析主机地址,请检查目标主机是否正确")
            # 关闭线程池,取消所有待执行任务
            executor.shutdown(wait=False, cancel_futures=True)

if __name__ == "__main__":
    target_host = "example.invalid"  # 用于测试gaierror的无效主机
    executor = ThreadPoolExecutor(max_workers=10)
    
    try:
        for port in range(1, 1026):
            if not error_occurred.is_set():
                executor.submit(scan_port, target_host, port)
        executor.shutdown(wait=True)
    except:
        pass

关键实现细节:

  • 线程安全标志:用threading.Event()创建error_occurred,确保多线程环境下只有第一个捕获到gaierror的线程会输出错误信息,后续线程检测到标志已设置会直接返回。
  • 立即终止线程池:捕获异常后调用executor.shutdown(wait=False, cancel_futures=True),cancel_futures=True会取消所有尚未开始执行的任务,wait=False让主线程不等待已运行的线程结束(已运行的线程会通过检查error_occurred标志提前退出)。
  • 前置检查:在提交任务和扫描函数开头都检查error_occurred状态,尽可能减少不必要的任务提交和执行。

这样就能保证socket.gaierror异常只会被输出一次,并且程序会快速终止所有扫描任务。

内容的提问来源于stack exchange,提问作者gummy otter

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 07:27:30