zoukankan      html  css  js  c++  java
  • 使用Python检测局域网内IP地址使用情况

    来源:https://www.cnblogs.com/donlin-zhang/p/6812675.html

     

    在测试环境搭建的过程中,经常需要给服务器分配静态IP地址,由于不清楚当前局域网内部哪些IP地址是空闲的,所以经常需要一个一个的去试,才能找到一个可用的IP。在之前的一家公司工作的时候,用到过一个检测IP使用情况的工具,但是属于内部工具,无法获取到。于是乎便想,何不自己开发一个呢?

      说做便做,开发环境使用的是Python3.6+PyQt5. 如果你的环境不一样,可能会运行失败。

      源码地址:https://github.com/LuckyDL/easyPing--python3.6

      1、界面设计

      界面用QtDesigner来画的,先来一张原型图如下,每次只能测试一个网段的IP占用情况,0-255个小窗格用来显示IP地址的使用情况,默认为灰色,程序执行后,IP地址已使用的显示绿色,IP地址未被使用的显示红色。

      

      做界面的时候,255个小窗格画起来实在是要人命,于是就仅画出了窗口框架,将UI文件转成Python源码后,自己手动编写代码来实现255窗格布局。代码片段如下:

    复制代码
         self.gridlayout = QtWidgets.QGridLayout(self.widget1)
            self.gridlayout.setContentsMargins(0, 0, 0, 0)
            self.gridlayout.setObjectName("gridlayout")
            self.gridlayout.setSpacing(7)
    
            self.label_list = []
            list_index = 0
            for i in range(1, 17):
                for j in range(1, 17):
                    label = QtWidgets.QLabel(self.widget1)
                    label.setMinimumSize(QtCore.QSize(32, 15))
                    label.setStyleSheet("")
                    label.setAlignment(QtCore.Qt.AlignCenter)
                    label.setText(QtCore.QCoreApplication.translate("MyPing", str(list_index)))
                    self.label_list.append(label)
                    self.gridlayout.addWidget(label, i-1, j-1, 1, 1)
                    list_index += 1
    复制代码

     

      2、ping功能实现

      ping的实现方法有多种,最常用的当然是通过调用系统自带的ping功能来实现。

      Python来执行系统命令的方式有os.system(), os.popen(), subprocess等方法,在Python3.6的手册中表明,subprocess模块是用来替代os.system等函数的。因此我们也使用subprocess模块来调用ping

      python3.5中,subprocess增加了一个run函数,run函数创建有一个子进程来运行需要执行的命令,返回一个CompletedProcess实例,该函数基本上可以处理所有的应用场景,run是对subprocess.Popen的一层封装。

           python3.5以下可以使用subprocess.call(), subprocess.check_call()等函数来实现相同的功能,具体可查阅Python手册

    复制代码
    def get_ping_result(self, ip):
        '''
        检查对应的IP是否被占用
        '''
        cmd_str = "ping {0} -n 1 -w 600".format(ip)
        DETACHED_PROCESS = 0x00000008   # 不创建cmd窗口
        try:
            subprocess.run(cmd_str, creationflags=DETACHED_PROCESS, check=True)  # 仅用于windows系统
        except subprocess.CalledProcessError as err:
            self._ping_signal.emit(False, ip)
        else:
            self._ping_signal.emit(True, ip)
    复制代码

        说明:

      在默认情况下,使用subprocess.run()执行ping命令的时候,会弹出一个cmd窗口,当256个线程一起运行的时候,满屏的窗口,想想都很酸爽。。。

           在windows系统下,可以传入creationflags参数来使subprocess创建的子进程不生成console

      参考链接:https://stackoverflow.com/questions/7006238/how-do-i-hide-the-console-when-i-use-os-system-or-subprocess-call

      check参数为True时,函数将检测执行结果是否为0(此处0表示执行成功),非零则抛出异常。

        3、多线程

            在使用pyqt进行GUI编程的时候,如果涉及到需要长时间后台运行的操作,一般需要使用多线程的方式,否则界面会阻塞,直到后台运行结束,造成程序卡死的假象。

           在本程序实现,要实现256个地址的ping操作,如果单线程操作,肯定半天也无法得到结果,因此我们为每一个IP地址分配一个线程,最多256线程并发运行,1~2秒的时间即可得到整个网段的IP地址占用情况

           多线程实现核心代码如下:

    复制代码
    def start_ping(self):
        '''
        启动多线程
        '''
        self.reset_ui()
        startip = self.ui.startIP.text().split('.')
        endip = self.ui.endIP.text().split('.')
        tmp_ip = startip
    
        pthread_list = []
        for i in range(int(startip[3]), int(endip[3]) + 1):
            tmp_ip[3] = str(i)
            ip = '.'.join(tmp_ip)
            pthread_list.append(threading.Thread(target=self.get_ping_result, args=(ip,)))
        for item in pthread_list:
            item.setDaemon(True)
            item.start()
    复制代码

           

        子线程通过发射信号的方式来通知主程序执行结果,最终主程序根据运行结果渲染界面。

        全部源码可到GitHub下载,链接见文章头部。

  • 相关阅读:
    多线程:多线程设计模式(一):总体介绍
    javascript:12种JavaScript MVC框架之比较
    mysql 查询死锁语句
    charles 抓包工具破解方法
    java 自定义log类
    git统计日期之间的代码改动行数
    mac/linux自带定时任务执行crontab的使用
    python MD5步骤
    python 操作excel读写
    python logger日志工具类
  • 原文地址:https://www.cnblogs.com/yizhipanghu/p/9908114.html
Copyright © 2011-2022 走看看