1. 程式人生 > 其它 >利用Python執行緒池以及佇列模組實現PING掃描

利用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() 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: 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()