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

Python如何实现快速Ping sweep扫描 现有方案速度慢求高效解法

速度慢的核心原因

你写的两个实现都是串行逐IP发起ping请求,单IP ping默认超时时间在1-2秒左右,一个/24网段有254个可用地址,串行执行完自然需要数分钟。
要提速核心是两点:

  • 把串行请求改成并发执行,同时发起多个ping探测
  • 缩短不必要的长超时,跳过不需要探测的网段地址、广播地址
可直接落地的高效实现

方案1:线程池+ping3(改造成本最低,无额外系统依赖)

ping3是纯Python实现的ICMP探测库,不需要调用系统ping命令,没有子进程启动开销,配合标准库自带的线程池做并发,/24网段扫描通常3-8秒就能完成。

from netaddr import IPNetwork
from ping3 import ping
from concurrent.futures import ThreadPoolExecutor, as_completed

# 扫描配置
TARGET_CIDR = "192.168.1.0/24"
MAX_WORKERS = 50  # 并发数,建议30-100,过大会触发ICMP限流丢包
PING_TIMEOUT = 1  # 单次探测超时,单位秒,内网环境设0.5-1足够

def check_ip(ip: str) -> tuple[str, bool]:
    try:
        result = ping(ip, timeout=PING_TIMEOUT)
        return (ip, result is not None)
    except Exception:
        return (ip, False)

if __name__ == "__main__":
    # 跳过网段地址(.0)和广播地址(.255)
    ip_list = [
        str(ip) for ip in IPNetwork(TARGET_CIDR)
        if ip.words[-1] not in (0, 255)
    ]
    online = []
    with ThreadPoolExecutor(max_workers=MAX_WORKERS) as pool:
        tasks = [pool.submit(check_ip, ip) for ip in ip_list]
        for task in as_completed(tasks):
            ip, is_up = task.result()
            if is_up:
                online.append(ip)
                print(f"{ip} is up!")
    
    print(f"\n扫描结束,共探测到{len(online)}个在线IP:")
    print(online)

注意:Windows下运行需要管理员权限,Linux/macOS普通用户即可执行。

方案2:asyncio协程并发(资源开销更低,适合大网段扫描)

如果需要扫描/16这类更大的网段,用协程实现的并发比线程池资源占用更低,速度更快,/24网段通常2-5秒扫完。
首先安装依赖:pip install aioping

import asyncio
from netaddr import IPNetwork
from aioping import ping

TARGET_CIDR = "192.168.1.0/24"
PING_TIMEOUT = 1
MAX_CONCURRENT = 100  # 协程并发上限

async def check_ip(sem: asyncio.Semaphore, ip: str):
    async with sem:
        try:
            await ping(ip, timeout=PING_TIMEOUT)
            print(f"{ip} is up!")
            return ip
        except (TimeoutError, OSError):
            return None

async def main():
    sem = asyncio.Semaphore(MAX_CONCURRENT)
    ip_list = [
        str(ip) for ip in IPNetwork(TARGET_CIDR)
        if ip.words[-1] not in (0, 255)
    ]
    tasks = [check_ip(sem, ip) for ip in ip_list]
    res = await asyncio.gather(*tasks)
    online = [ip for ip in res if ip]
    print(f"\n扫描结束,共探测到{len(online)}个在线IP:")
    print(online)

if __name__ == "__main__":
    asyncio.run(main())
额外优化建议
  • 不要用shell=True的subprocess调用系统ping命令,子进程创建、shell解析的额外开销远大于直接用Python ICMP库,还存在命令注入风险
  • 内网环境超时时间不要设超过1秒,绝大多数在线设备的ICMP响应延迟都在10ms以内,长超时只会拖慢整体速度
  • 并发数不要盲目开太大,超过100之后很容易因为本地网络栈瓶颈、目标网络ICMP限流出现误判,把在线IP识别为离线

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 20:33:08