利用python实现IP扫描
需求:寫(xiě)一個(gè)腳本,判斷192.168.11.0/24網(wǎng)絡(luò)里,當(dāng)前在線ip有哪些?
知識(shí)點(diǎn):
1 使用subprocess模塊,來(lái)調(diào)用系統(tǒng)命令,執(zhí)行ping 192.168.11.xxx 命令
2 調(diào)用系統(tǒng)命令執(zhí)行ping命令的時(shí)候,會(huì)有返回值(ping的結(jié)果),需要用到stdout=fnull, stderr=fnull方法,屏蔽系統(tǒng)執(zhí)行命令的返回值
常規(guī)版本(代碼)
import os
import time
import subprocess
def ping_call():start_time = time.time()fnull = open(os.devnull, 'w')for i in range(1, 256):ipaddr = 'ping 192.168.11.' + str(i)result = subprocess.call(ipaddr + ' -n 2', shell=True, stdout=fnull, stderr=fnull)current_time = time.strftime('%Y%m%d-%H:%M:%S', time.localtime())if result:print('時(shí)間:{} ip地址:{} ping fall'.format(current_time, ipaddr))else:print('時(shí)間:{} ip地址:{} ping ok'.format(current_time, ipaddr))print('程序耗時(shí){:.2f}'.format(time.time() - start_time))fnull.close()
ping_call()
執(zhí)行效果:
上面的執(zhí)行速度非常慢,怎么能讓程序執(zhí)行速度快起來(lái)?
python提供了進(jìn)程,線程,協(xié)程。分別用這三個(gè)對(duì)上面代碼改進(jìn),提高執(zhí)行效率,測(cè)試一波效率
進(jìn)程池異步執(zhí)行 – 開(kāi)啟20個(gè)進(jìn)程
import os
import time
import subprocess
from multiprocessing import Pool
def ping_call(num):fnull = open(os.devnull, 'w')ipaddr = 'ping 192.168.11.' + str(num)result = subprocess.call(ipaddr + ' -n 2', shell=True, stdout=fnull, stderr=fnull)current_time = time.strftime('%Y%m%d-%H:%M:%S', time.localtime())if result:print('時(shí)間:{} ip地址:{} ping fall'.format(current_time, ipaddr))else:print('時(shí)間:{} ip地址:{} ping ok'.format(current_time, ipaddr))fnull.close()if __name__ == '__main__':start_time = time.time()p = Pool(20)res_l = []for i in range(1, 256):res = p.apply_async(ping_call, args=(i,))res_l.append(res)for res in res_l:res.get()print('程序耗時(shí){:.2f}'.format(time.time() - start_time))
執(zhí)行結(jié)果:
線程池異步執(zhí)行 – 開(kāi)啟20個(gè)線程
import os
import time
import subprocess
from concurrent.futures import ThreadPoolExecutor
def ping_call(num):fnull = open(os.devnull, 'w')ipaddr = 'ping 192.168.11.' + str(num)result = subprocess.call(ipaddr + ' -n 2', shell=True, stdout=fnull, stderr=fnull)current_time = time.strftime('%Y%m%d-%H:%M:%S', time.localtime())if result:print('時(shí)間:{} ip地址:{} ping fall'.format(current_time, ipaddr))else:print('時(shí)間:{} ip地址:{} ping ok'.format(current_time, ipaddr))fnull.close()if __name__ == '__main__':start_time = time.time()thread_pool = ThreadPoolExecutor(20)ret_lst = []for i in range(1, 256):ret = thread_pool.submit(ping_call, i)ret_lst.append(ret)thread_pool.shutdown()for ret in ret_lst:ret.result()print('線程池(20)異步-->耗時(shí){:.2f}'.format(time.time() - start_time))
執(zhí)行結(jié)果:
協(xié)程執(zhí)行—(執(zhí)行多個(gè)任務(wù),遇到I/O操作就切換)
使用gevent前,需要pip install gevent
from gevent import monkey;monkey.patch_all()
import gevent
import os
import time
import subprocessdef ping_call(num):fnull = open(os.devnull, 'w')ipaddr = 'ping 192.168.11.' + str(num)result = subprocess.call(ipaddr + ' -n 2', shell=True, stdout=fnull, stderr=fnull)current_time = time.strftime('%Y%m%d-%H:%M:%S', time.localtime())if result:print('時(shí)間:{} ip地址:{} ping fall'.format(current_time, ipaddr))else:print('時(shí)間:{} ip地址:{} ping ok'.format(current_time, ipaddr))fnull.close()def asynchronous(): # 異步g_l = [gevent.spawn(ping_call, i) for i in range(1, 256)]gevent.joinall(g_l)if __name__ == '__main__':start_time = time.time()asynchronous()print('協(xié)程執(zhí)行-->耗時(shí){:.2f}'.format(time.time() - start_time))
執(zhí)行結(jié)果:
遇到I/O操作,協(xié)程的效率比進(jìn)程,線程高很多!
總結(jié):python中,涉及到I/O阻塞的程序中,使用協(xié)程的效率最高
最后附帶協(xié)程池代碼
gevent.pool
from gevent import monkey;monkey.patch_all()
import gevent
import os
import time
import subprocess
import gevent.pooldef ping_call(num):fnull = open(os.devnull, 'w')ipaddr = 'ping 192.168.11.' + str(num)result = subprocess.call(ipaddr + ' -n 2', shell=True, stdout=fnull, stderr=fnull)current_time = time.strftime('%Y%m%d-%H:%M:%S', time.localtime())if result:print('時(shí)間:{} ip地址:{} ping fall'.format(current_time, ipaddr))else:print('時(shí)間:{} ip地址:{} ping ok'.format(current_time, ipaddr))fnull.close()if __name__ == '__main__':start_time = time.time()res_l = []p = gevent.pool.Pool(100)for i in range(1, 256):res_l.append(p.spawn(ping_call, i))gevent.joinall(res_l)print('協(xié)程池執(zhí)行-->耗時(shí){:.2f}'.format(time.time() - start_time))
執(zhí)行結(jié)果:
總結(jié)
以上是生活随笔為你收集整理的利用python实现IP扫描的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Python中正则匹配与中文的问题
- 下一篇: python简介、安装及基本设置