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

Python端口扫描如何仅检测IPv4端口 解决AF_INET误报IPv6占用问题

问题原因

多数主流操作系统默认关闭了IPv6套接字的IPV6_V6ONLY参数,此时绑定到::+端口的IPv6套接字会同时占用对应端口的IPv4、IPv6双栈入口,导致使用AF_INET(IPv4)套接字绑定0.0.0.0时触发端口占用报错,无法区分是IPv4本身被占还是被IPv6关联占用。

解决方案

通过二次校验逻辑即可实现准确的IPv4端口占用检测,无需引入第三方依赖,调整后代码如下:

import socket
import errno

def is_ipv4_port_available(port):
    # 尝试绑定IPv4通配地址
    s_ipv4 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    try:
        s_ipv4.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        s_ipv4.bind(("0.0.0.0", port))
        s_ipv4.close()
        return True
    except socket.error as e:
        s_ipv4.close()
        if e.errno != errno.EADDRINUSE:
            return False
        # 触发端口占用报错时,校验是否为IPv6独占导致的误报
        s_ipv6 = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
        try:
            s_ipv6.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 1)
            s_ipv6.bind(("::", port))
            s_ipv6.close()
            # IPv6绑定成功,说明原报错为IPv6占用导致,IPv4端口实际可用
            return True
        except socket.error:
            s_ipv6.close()
            # IPv6也绑定失败,说明端口确实被IPv4服务占用
            return False

# 测试调用
port = 80
if is_ipv4_port_available(port):
    print(f"IPv4端口{port}可用")
else:
    print(f"IPv4端口{port}已被占用")
逻辑说明
  • 第一次绑定IPv4通配地址成功,直接判定端口可用
  • 第一次绑定报端口占用错误时,创建开启IPV6_V6ONLY参数的IPv6套接字尝试绑定同端口
    • 若IPv6绑定成功:说明之前的报错是未开启IPV6_V6ONLY的IPv6套接字占用端口导致的误判,IPv4侧实际可用
    • 若IPv6绑定也报端口占用:说明端口确实已经被IPv4服务占用
  • 代码中加入SO_REUSEADDR参数是为了规避处于TIME_WAIT状态的连接导致的误判,不需要可直接删除

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 21:45:04