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

为何无法捕获Socket超时异常?设置settimeout后仍无异常触发

为什么你的端口扫描代码没触发超时?

嘿,我明白你的困惑了——你明明设置了套接字超时,但既没触发超时逻辑,也捕获不到异常,对吧?问题出在你用的connect_ex()方法上,它的行为和你预想的完全不一样。

核心原因:connect_ex()不会抛出异常

普通的connect()方法在超时或者连接失败时会直接抛出异常,但connect_ex()的设计目的就是不抛出异常,而是返回一个整数错误码:

  • 返回0表示连接成功(端口开放)
  • 返回非0值表示连接失败,不同数值对应不同错误类型(比如超时、端口关闭、拒绝连接等)

所以哪怕你打开了settimeout(0.5),当连接超时时,connect_ex()不会触发try块里的异常,而是返回一个对应超时的错误码(比如errno.EAGAIN或errno.EWOULDBLOCK,具体取决于系统),但你的代码只判断了返回值是否为0,其他情况都直接归为“关闭的端口”,超时情况被你当成普通关闭端口处理了,自然看不到超时提示。

怎么修复?

有两种常用的解决思路:

方法1:改用connect()捕获异常

如果你想通过捕获异常来处理超时,把connect_ex()换成普通的connect(),这样超时时会抛出socket.timeout异常,你可以在except块里单独处理:

import socket
HOST = 'x.x.x.x'
open_ports = []
closed_ports = []
timeout_ports = []

def scan(PORT):
    sock_tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock_tcp.settimeout(0.5)  # 启用超时设置
    SERVER_ADDR = (HOST, PORT)
    try:
        sock_tcp.connect(SERVER_ADDR)  # 用connect()替代connect_ex()
        open_ports.append(PORT)
        print(f"{PORT} is OPEN")
    except socket.timeout:
        timeout_ports.append(PORT)
        print(f"{PORT} timed out")
    except socket.error as e:
        closed_ports.append(PORT)
        print(f"{PORT} is CLOSED: {e}")
    finally:
        sock_tcp.close()  # 记得关闭套接字,避免资源泄漏

方法2:检查connect_ex()的返回码

如果你坚持用connect_ex(),可以导入errno模块,判断返回的错误码是否对应超时,再单独处理:

import socket
import errno
HOST = 'x.x.x.x'
open_ports = []
closed_ports = []
timeout_ports = []

def scan(PORT):
    sock_tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock_tcp.settimeout(0.5)
    SERVER_ADDR = (HOST, PORT)
    portStatusTCP = sock_tcp.connect_ex(SERVER_ADDR)
    if portStatusTCP == 0:
        open_ports.append(PORT)
        print(f"{PORT} is OPEN")
    elif portStatusTCP in (errno.EAGAIN, errno.EWOULDBLOCK):
        timeout_ports.append(PORT)
        print(f"{PORT} timed out")
    else:
        closed_ports.append(PORT)
        print(f"{PORT} is CLOSED, error code: {portStatusTCP}")
    sock_tcp.close()

另外提个小细节:原代码里没有关闭套接字,处理完后调用close()能避免不必要的资源浪费哦。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 07:02:40