python3 线程池实现批量ping某一网段,获得可用ip列表——futures模块
发布日期:2021-05-04 20:52:49 浏览次数:28 分类:精选文章

本文共 3632 字,大约阅读时间需要 12 分钟。

一、工作中需要找出指定网段里,哪些ip是没被占用的,然后使用这些ip。

实现方法很简单,就是依次ping一下,看看哪些是不通的,就代表没被占用。ping是很耗时间的,于是想到多线程,考虑到线程数量多且每个线程的任务很简单,所以使用线程池。参考了网上博主的代码,原文链接:《》,主要学到了Python队列queue的概念和后台调用cmd控制台的方法。

我的代码如下:

第一个参数 net_segment 代表要查找的网段,第二个参数 ip_num 代表所需ip的数量。通过修改 max_workers=100 的值可以调整程序运行的速度。

import timeimport threadingimport subprocessfrom queue import Queuefrom concurrent.futures import ThreadPoolExecutor, wait, ALL_COMPLETEDdef get_ip_list(net_segment, ip_num):    # 创建一个队列    IP_QUEUE = Queue()    ip_list = []    list_segment = net_segment.split('.')    ip_index = 1    # 将需要 ping 的 ip 加入队列    for i in range(1, 254):        list_segment[-1] = str(ip_index + i)        addr = ('.').join(list_segment)        IP_QUEUE.put(addr)    # 定义一个执行 ping 的函数    def ping_ip(ip):        res = subprocess.call('ping -n 2 -w 5 %s' % ip, stdout=subprocess.PIPE)  # linux 系统将 '-n' 替换成 '-c'        # 打印运行结果        print(ip, True if res == 0 else False)        if res != 0:            if lock.acquire():                if len(ip_list) < ip_num:                    ip_list.append(ip)                lock.release()    # 创建一个最大任务为100的线程池    pool = ThreadPoolExecutor(max_workers=100)    lock = threading.Lock()    start_time = time.time()    all_task = []    while not IP_QUEUE.empty():        all_task.append(pool.submit(ping_ip, IP_QUEUE.get()))    # 等待所有任务结束    wait(all_task, return_when=ALL_COMPLETED)    print('ping耗时:%s' % (time.time() - start_time))    if len(ip_list) < ip_num:        print("Warning:当前网段可用ip不够,需要数量:%s,可用数量:%s" % (str(ip_num), str(len(ip_list))))    return ip_listif __name__ == '__main__':    ip_list = get_ip_list("202.169.50.0", 200)    print(ip_list)    print(len(ip_list))

部分运行结果:

202.169.50.238 False

202.169.50.253 False
202.169.50.239 False
202.169.50.230 False
ping耗时:6.348670959472656
Warning:当前网段可用ip不够,需要数量:200,可用数量:168
['202.169.50.3', '202.169.50.20', '202.169.50.19', '202.169.50.78',…………………………………………………………]
168

 二、代码稍作修改,可以查看某两个ip之间哪些地址ping的通,哪些ping不通。

这里用到处理ip地址的标准库 ipaddress 模块,来处理ip地址的计算。

import timeimport threadingimport subprocessfrom queue import Queuefrom concurrent.futures import ThreadPoolExecutor, wait, ALL_COMPLETEDfrom ipaddress import ip_addressdef get_ip_list(ip_start, ip_end):    # 创建一个队列    IP_QUEUE = Queue()    ip_used = []    ip_not_used = []    ip_start = ip_address(ip_start)    ip_end = ip_address(ip_end)    while ip_start <= ip_end:        IP_QUEUE.put(str(ip_start))        ip_start += 1    # 定义一个执行 ping 的函数    def ping_ip(ip):        res = subprocess.call('ping -n 2 -w 5 %s' % ip, stdout=subprocess.PIPE)  # linux 系统将 '-n' 替换成 '-c'        # 打印运行结果        print(ip, True if res == 0 else False)        if lock.acquire():            if res == 0:                ip_used.append(ip)            else:                ip_not_used.append(ip)            lock.release()    # 创建一个最大任务为100的线程池    pool = ThreadPoolExecutor(max_workers=120)    lock = threading.Lock()    start_time = time.time()    all_task = []    while not IP_QUEUE.empty():        all_task.append(pool.submit(ping_ip, IP_QUEUE.get()))    # 等待所有任务结束    wait(all_task, return_when=ALL_COMPLETED)    print('ping耗时:%s' % (time.time() - start_time))    return ip_used, ip_not_usedif __name__ == '__main__':    ip_used, ip_not_used = get_ip_list("202.169.50.1", "202.169.51.255")    print(str(len(ip_used))+"已用", "\n", ip_used)    print(str(len(ip_not_used))+"未用", "\n", ip_not_used)

部分运行结果:

202.169.51.222 False

202.169.51.249 False
202.169.51.200 False
202.169.51.208 False
ping耗时:10.248608827590942
86已用
 ['202.169.50.2', '202.169.50.8', '202.169.50.7',…………………………………………]
425未用
 ['202.169.50.3', '202.169.50.19', '202.169.50.78'…………………………………………]

上一篇:彻底弄懂python3中的回调函数
下一篇:我认识到了记录博客对于工作和学习的重要性

发表评论

最新留言

第一次来,支持一个
[***.219.124.196]2025年04月14日 09时05分24秒