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
相关产品推荐
相关产品推荐

