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

如何向异步socket函数传参并解决异步端口扫描阻塞问题

问题根因

你的代码实际还是同步串行执行,核心问题有两个:

  • 你调用的是标准库socket自带的阻塞式connect()方法,这个方法执行时会卡住整个线程,不会把执行权交还给asyncio事件循环。哪怕把它包在async def定义的协程里,运行时依然是一个连接跑完才会跑下一个,完全没有并发效果。
  • 你全局只创建了1个socket实例,所有端口扫描任务共用这一个socket。而TCP连接本身是点对点的,单个socket同一时间只能维持一条连接,从逻辑上就不可能同时扫描多个端口。
正确实现方案

用asyncio原生提供的异步网络接口asyncio.open_connection替代阻塞的socket.connect,每个端口扫描任务独立处理连接,不要共用全局socket实例,修正后的代码如下:

import asyncio
import time

target = '72.221.171.130'
t1 = time.time()

async def connect(port):
    try:
        # 等待连接的过程会自动交还控制权给事件循环,不会阻塞其他任务
        reader, writer = await asyncio.wait_for(
            asyncio.open_connection(target, port),
            timeout=2
        )
        print(f"端口{port}开放")
        # 用完及时关闭连接
        writer.close()
        await writer.wait_closed()
    except Exception:
        # 连接超时、被拒绝直接跳过即可
        pass

async def main():
    # 并发发起所有端口的扫描任务
    tasks = [connect(port) for port in range(4100, 4150)]
    await asyncio.gather(*tasks)
    print(f'端口扫描耗时: {round((time.time() - t1),3)} 秒')

if __name__ == "__main__":
    # Python3.7+ 直接用asyncio.run启动事件循环即可,无需手动获取loop
    asyncio.run(main())

这段代码的实际运行耗时基本等于你设置的连接超时时间,通常2-3秒就能扫完指定端口段,不会出现20秒串行等待的问题。

额外注意:

  • 不要在asyncio协程里直接调用任何阻塞式IO方法,比如原生socket的收发接口、requests库的HTTP请求、time.sleep()等。如果一定要用这类阻塞逻辑,需要用loop.run_in_executor把阻塞任务丢到独立线程池运行,否则会卡住整个事件循环,异步逻辑直接退化成串行同步。你之前测试requests、httpio时遇到的异步失效问题,本质也是这个原因:requests是纯阻塞实现,原生不支持asyncio调度,要做异步HTTP请求请选用aiohttp这类原生异步实现的库。
  • 异步函数传参逻辑和普通Python函数完全一致,支持位置参数、关键字参数、多参数传递,你之前代码里给connect(port)传入端口参数的写法本身没有问题,性能问题和传参无关。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 03:09:44