【Python】局域网ping扫描在线主机

  • Post author:
  • Post category:python


首先参考了

这个实现


它是开多线程来调用cmd ping

LZ选择用subprocess.Popen,让子进程通过管道将输入缓存到系统buffer中。Popen会返回一个对象,可以通过它与子进程交互,获取其状态等。轮询Popen对象判断ping是否结束,进而检查echo信息判断,得到在线主机列表。。

速度比多线程快很多,扫描1-255只需要不到10s

#-*- coding: utf-8 -*- 
import platform 
import sys 
import os 
import time 
import thread
from subprocess import Popen, PIPE

# 传入ip地址,调用 cmd ping, 返回 Popen 对象
# 指定ping的stdout通过管道写入设定的buffer中
def invoke_ping(addr):
    # windows 的参数和linux下不同
    cmd = ['ping', '-n', '1', addr]
    ret = 0
    try:
        ret = Popen(cmd, bufsize=1024, stdout=PIPE)
    except ValueError:
        print 'error occur in invoke_ping: ' + addr
    return ret

# 简单地通过 ping 回显信息检查是否在线
def check_online(popen_obj):
    echo = popen_obj.communicate()[0].split('\n')
    if len(echo) >= 3:
        print echo[2]
        ttl_pos = echo[2].find('TTL')
        if ttl_pos != -1:
            ms_pos = echo[2].find('ms')
            i = ms_pos - 1
            while i > 0 and echo[2][i:i+1].isdigit() == True:
                i -= 1
            ti = int(echo[2][i+1:ms_pos])
            ttl = int(echo[2][ttl_pos + 4:])

            return (ti, ttl)
    return tuple()

def ping_scan(dst):
    oks = []
    scq = {}
    net_addr = dst.split('.')
    for i in range(0, 256):
        net_addr[3] = str(i)
        tmp = invoke_ping( '.'.join(net_addr) )
        if type(tmp) != int:
            scq[i] = tmp

    while len(scq) != 0:
        to_be_removed = []
        for k, v in scq.items():
            if v.poll() != None:
                ret = check_online(v)
                if len(ret) > 0:
                    net_addr[3] = str(k)
                    oks.append( ( k, ret) )
                to_be_removed.append( k )
        for i in to_be_removed:
            scq.pop(i)
    return oks

if __name__ == '__main__':
    start_time = time.clock()
    dst_net = '172.30.58.229'
    online_list = ping_scan(dst_net)
    online_list.sort()
    prefix = '.'.join( dst_net.split('.')[0:3] )
    for i in online_list:
        fmt = '%s time=%dms ttl=%d'
        print fmt % ( prefix+'.'+str(i[0]), i[1][0], i[1][1] )
    print '%d hosts in total' % len(online_list)
    print 'process time: %lfs' % (time.clock() - start_time)



版权声明:本文为slowlight93原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。