为何无法捕获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
相关产品推荐
相关产品推荐

