参考链接:https://blog.csdn.net/weixin_43484977/article/details/103339073

python 模拟ping值检测

  • 先创建一个aaa.txt文档,里面每一行存一个ip地址
import threading
import os
import struct
import array
import time
import socket
import threading


class SendPingThread(threading.Thread): #发送ping线程,继承Thread
    def __init__(self, ipPool, icmpPacket, icmpSocket, timeout=0.5): #ip池,icmp协议包,icmp协议套接字,超时时间
        threading.Thread.__init__(self)
        self.sock = icmpSocket
        self.ipPool = ipPool
        self.packet = icmpPacket
        self.timeout = timeout
        self.sock.settimeout(timeout)

    def run(self): #run方法  start的时候调用
        time.sleep(0.01)
        for ip in self.ipPool: #遍历ip地址池
            try:
                self.sock.sendto(self.packet, (ip, 0)) #发送消息 # 利用套截字发送icmp包
            except socket.timeout: #超时异常
                break



class AliveScan:
    def __init__(self, timeout=3):
        self.timeout = timeout
        self._data = struct.pack('d', time.time()) #按d类型打包,把时间戳打包,生成8个字节的字节类型对象
        self._id = os.getpid() #进程id 作为报文中的Identifier字段(必须是int)

    @property
    def icmp_socket(self): #创建套接字
        sock = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.getprotobyname("icmp"))
        return sock

    def check_sum(self, packet): #计算校验和
        if len(packet) & 1:
            packet = packet + '\0'
        words = array.array('h', packet)
        sum = 0
        #为了计算一份数据报的IP检验和,首先把检验和字段置为0。
        # 然后,对首部中每个16bit进行二进制反码求和(整个首部看成是由一串16bit的字组成),结果存在检验和字段中。
        for word in words: #对每一个16bits (字)进行反码求和
            sum += (word & 0xffff)
        sum = (sum >> 16) + (sum & 0xffff)
        sum = sum + (sum >> 16)
        return (~sum) & 0xffff


    @property
    def icmp_packet(self): #icmp包
        header = struct.pack('bbHHh', 8, 0, 0, self._id, 0) #报文头 pack 的时候 按照参数个数进行pack, 前面的bbHHh是类型,
        packet = header + self._data # 报文头+数据 d 得到包 这里的+ 是单纯的连在一起么?
        chkSum = self.check_sum(packet)  #把包进行校验
        header = struct.pack('bbHHh', 8, 0, chkSum, self._id, 0) #再pack打包
        return header + self._data


    def hot_ping(self, ipPool): #ip池 传进来,循环
        sock = self.icmp_socket
        sock.settimeout(self.timeout)
        packet = self.icmp_packet
        recvFroms = set() #空集合
        sendThr = SendPingThread(ipPool, packet, sock, self.timeout) #创建发送线程
        sendThr.start() #启动,自动调用run方法,发送icmp包了已经
        while True:
            try:
                msg,addr = sock.recvfrom(1024) #接受信息,获取到地址,那么这里接收到的msg里面有时间戳么,怎么获取时间戳,然后计算ping值响应时间?
                # 接收返回值
                if addr[0] not in ipPool: #如果ping不通,接收到的是本机地址,本机地址不在ipPool池里
                    print('不通')
                else:print('通')
            except Exception:
                pass
            finally:
                if not sendThr.is_alive(): #线程不是激活的状态,就结束循环
                    break
        return recvFroms & ipPool  #交集


def get_alive_ip():
    s = AliveScan() #实例化扫描类
    ipPool = set() #空集合 ip池
    with open('aaa.txt') as file_obj:
        ips = file_obj.read()
        ips_list = ips.strip().split('\n')
        ipPool = set(ips_list[:20]) #列表切片, 只取前20个 放到集合中
        alive_ip_set = set()
        for ip in ipPool:
            print('ping '+ip)
            alive_ips = s.hot_ping(set([ip, ]))
            if alive_ips:
                # print type(alive_ips)
                alive_ip_set = alive_ip_set | alive_ips #取并集
    return alive_ip_set

get_alive_ip()
  • 结果:
posted on 2020-09-02 17:18  94小渣渣  阅读(94)  评论(0)    收藏  举报