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

Python端口扫描器单端口扫描正常,批量扫描结果异常求助

Python端口扫描器批量扫描异常问题分析与解决

问题描述

开发的Python端口扫描器在单端口扫描时结果准确,但批量扫描所有端口时,结果与单端口扫描不一致,且每次批量扫描的开放端口随机变化(仅扫描路由器时53端口始终显示开放)。

单端口扫描代码及结果

#! /usr/bin/python
import socket

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

host = "192.168.1.8"
port = 443

def portscanner():
    if sock.connect_ex((host,port)):
        print ("Port %d is closed" % (port))
    else:
        print("Port %d is open" % (port))

portscanner()

运行结果:

Port 443 is open.

批量扫描代码及异常结果

#! /usr/bin/python
    
import socket

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

host = "192.168.1.1"

def portscanner():
    
    closed = 0
    opened  = 0

    for port in range (0, 65535):
    
        if sock.connect_ex((host,port)):
            closed += 1
        else:
            print("Port %d is open" % (port))
            opened += 1

    print_port(closed, opened)

def print_port(closed, opened):
    print ("%d ports are opened" % (opened))
    print ("%d ports are closed" % (closed))

portscanner()

第一次运行结果:

Port 34452 is open
1 ports are opened
65534 ports are closed

再次运行结果:

Port 52016 is open
1 ports are opened
65534 ports are closed

扫描路由器时结果:

Port 53 is open
1 ports are opened
65534 ports are closed

问题根源

核心错误是复用了同一个TCP Socket对象。TCP是面向连接的协议,Socket对象在完成一次connect_ex调用后,内部状态会发生改变(无论连接成功或失败),无法再用于后续的连接操作。后续循环中复用该Socket调用connect_ex时,返回的结果是未定义的随机错误码,导致端口状态误判。

路由器53端口(DNS服务)每次都显示开放,是因为第一次扫描到该端口时Socket状态正常,连接成功;后续的端口扫描因Socket状态异常返回错误结果,但不影响已输出的53端口结果。

修复方案

每次扫描端口时创建新的Socket对象,确保每次连接都处于初始状态,同时添加超时设置提升扫描效率:

#! /usr/bin/python
import socket

host = "192.168.1.1"

def portscanner():
    closed = 0
    opened = 0

    # 扫描1-65535端口(0为保留端口,无需扫描)
    for port in range(1, 65536):
        # 每次循环创建新的Socket
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        # 设置超时时间,避免等待过长
        sock.settimeout(0.1)
        # 尝试连接端口
        result = sock.connect_ex((host, port))
        if result == 0:
            print(f"Port {port} is open")
            opened += 1
        else:
            closed += 1
        # 关闭Socket释放资源
        sock.close()

    print_port(closed, opened)

def print_port(closed, opened):
    print(f"{opened} ports are opened")
    print(f"{closed} ports are closed")

portscanner()

修改说明

  • 每次循环内新建Socket,保证连接状态初始化为新
  • 添加settimeout设置,避免扫描未开放端口时阻塞过久
  • 扫描完成后关闭Socket,释放系统资源
  • 调整端口范围为1-65535,跳过无实际意义的保留端口0

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 11:05:30