利用Python线程池以及队列模块实现PING扫描

  本工具开始编写的时候使用多线程模块threading,但是发现运行的时候会报出很多的错误,其中一个解决办法是在创建的新的线程的时候,time.sleep()一定的时间,但这就从一定程度上失去了多线程的意义,还有一个比较简便的办法是利用线程池,ThreadPoolExecutor,可以指定线程池中的线程数,然后由ThreadPoolExecutor进行调度。

  此外,子线程与主线程之间的变量是不能共享的,比如起初设想用列表存放活跃主机self.alive_hosts = [],但最后这个结果是错误的,因此需要用queue模块来存储这样的共享变量,然后在主线程中打印显示出来。

 1 from scapy.all import *
 2 import logging
 3 import optparse
 4 import sys
 5 import ipaddress
 6 import threading    #开始用的是threading模块,后来改用线程池模块
 7 import time
 8 import queue
 9 from concurrent.futures import ThreadPoolExecutor
10 
11 logging.getLogger('scapy.runtime').setLevel(logging.ERROR)
12 
13 class PingNetwork:
14     def __init__(self) -> None:
15         self.network = self.get_params()   #目标网络(格式:192.168.140.0/24)
16         self.alive_hosts = []              #如果不用多线程,那么这个列表可以作为存放活跃主机的变量,但是如果用多线程,需要用队列
17         self.q = queue.Queue()
18         
19 
20     def get_params(self):
21         parser = optparse.OptionParser('Usage: < Program > -n network')
22         parser.add_option('-n', '--network', dest='network', type='string', help='Specify network to scan')
23         options, args = parser.parse_args()
24         if options.network is None:
25             print(parser.usage)
26             sys.exit(0)
27         try:
28             network = ipaddress.ip_network(options.network)   #对于用户输入的网络参数通过ipaddress模块转换为相应的迭代对象
29             return network
30         except:
31             print("[-] Input ip network wirth right format. e.g 192.168.4.0/24")
32             sys.exit()
33     
34     def icmp_host(self, ip):
35         try:
36             packet = IP(dst=ip)/ICMP()
37             res = sr1(packet, timeout=2, verbose=False)
38             # print(res, type(res))
39             if res:
40                 if res.type == 0:                 #判断是否为echo-reply
41                     # print("="*100)
42                     self.q.put(ip)
43         except:
44             pass
45     
46     def run(self):
47         with ThreadPoolExecutor(30) as t:   #这里用到线程池,并指定了线程数为30
48             for ip in self.network:
49                 ip = str(ip)             
50                 t.submit(self.icmp_host, ip=ip)          #submit方法与threading.Thread中方法的传入参数的方式不一样
51         
52 
53         if self.q.empty():
54         
55             print("[0] No online host found!")
56         else:
57             while not self.q.empty():
58                 print("[-] Online hosts as follows: \n")
59             
60                 print("\t%s" % self.q.get())
61 
62 if __name__ == "__main__":
63     pinger = PingNetwork()
64     pinger.run()

 

posted @ 2022-05-28 18:59  Jason_huawen  阅读(94)  评论(0编辑  收藏  举报