配置我就不说了,在我上一个博客里面说过的,直接上代码
Ui_host_alive_MainWindow
# -*- coding: utf-8 -*-
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QMessageBox, QApplication
from PyQt5.QtCore import QBasicTimer
import sys, easygui, os
import pinger
from queue import Queue
class Ui_host_alive_MainWindow(QtWidgets.QWidget):
def setupUi(self, host_alive_MainWindow):
self.address = []
self.address_res = []
self.address_fail = []
self.que = Queue()
self.total_num = 1
self.count_num = 0
self.success_num = 0
self.fail_num = 0
# 主窗口设置
host_alive_MainWindow.setObjectName("host_alive_MainWindow")
host_alive_MainWindow.resize(800, 555)
host_alive_MainWindow.setFixedSize(MainWindow.width(), MainWindow.height())
# 字体设置
font = QtGui.QFont()
font.setPointSize(10)
host_alive_MainWindow.setFont(font)
# 设置ping标签
self.centralwidget = QtWidgets.QWidget(host_alive_MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.ping_label = QtWidgets.QLabel(self.centralwidget)
self.ping_label.setGeometry(QtCore.QRect(10, 9, 51, 31))
font = QtGui.QFont()
font.setPointSize(12)
self.ping_label.setFont(font)
self.ping_label.setObjectName("ping_label")
# 设置ping栏
self.ping_lineEdit = QtWidgets.QLineEdit(self.centralwidget)
self.ping_lineEdit.setGeometry(QtCore.QRect(60, 10, 151, 31))
self.ping_lineEdit.setContextMenuPolicy(QtCore.Qt.DefaultContextMenu)
self.ping_lineEdit.setObjectName("ping_lineEdit")
# 设置加载按钮
self.load_Button = QtWidgets.QPushButton(self.centralwidget)
self.load_Button.setGeometry(QtCore.QRect(220, 10, 51, 28))
self.load_Button.setObjectName("load_Button")
self.load_Button.clicked.connect(self.on_click_load)
# 设置加载文件按钮
self.loadfile_Button = QtWidgets.QPushButton(self.centralwidget)
self.loadfile_Button.setGeometry(QtCore.QRect(280, 10, 91, 28))
self.loadfile_Button.setObjectName("loadfile_Button")
self.loadfile_Button.clicked.connect(self.on_click_load_file)
# 设置清除按钮
self.clear_Button = QtWidgets.QPushButton(self.centralwidget)
self.clear_Button.setGeometry(QtCore.QRect(380, 10, 51, 28))
self.clear_Button.setObjectName("clear_Button")
self.clear_Button.clicked.connect(self.on_click_clear)
# 设置多线程标签
self.thread_label = QtWidgets.QLabel(self.centralwidget)
self.thread_label.setGeometry(QtCore.QRect(440, 9, 81, 31))
font = QtGui.QFont()
font.setPointSize(12)
self.thread_label.setFont(font)
self.thread_label.setObjectName("thread_label")
# 设置多线程数目
self.thread_spinBox = QtWidgets.QSpinBox(self.centralwidget)
self.thread_spinBox.setGeometry(QtCore.QRect(510, 10, 46, 28))
font = QtGui.QFont()
font.setPointSize(12)
self.thread_spinBox.setFont(font)
self.thread_spinBox.setMaximum(500)
self.thread_spinBox.setProperty("value", 10)
self.thread_spinBox.setObjectName("thread_spinBox")
# 设置开始按钮
self.action_Button = QtWidgets.QPushButton(self.centralwidget)
self.action_Button.setGeometry(QtCore.QRect(570, 10, 93, 28))
self.action_Button.setObjectName("action_Button")
self.action_Button.clicked.connect(self.on_click_action)
# 设置输出按钮
self.output_value_Button = QtWidgets.QPushButton(self.centralwidget)
self.output_value_Button.setGeometry(QtCore.QRect(680, 10, 93, 28))
self.output_value_Button.setObjectName("output_value_Button")
self.output_value_Button.clicked.connect(self.on_click_output_value)
# 设置输入ip地址标签
self.input_ip_label = QtWidgets.QLabel(self.centralwidget)
self.input_ip_label.setGeometry(QtCore.QRect(10, 210, 71, 31))
font = QtGui.QFont()
font.setPointSize(12)
self.input_ip_label.setFont(font)
self.input_ip_label.setFocusPolicy(QtCore.Qt.NoFocus)
self.input_ip_label.setLayoutDirection(QtCore.Qt.LeftToRight)
self.input_ip_label.setTextFormat(QtCore.Qt.AutoText)
self.input_ip_label.setObjectName("input_ip_label")
# 设置输入ip栏
self.input_ip_textEdit = QtWidgets.QTextEdit(self.centralwidget)
self.input_ip_textEdit.setGeometry(QtCore.QRect(80, 60, 181, 341))
self.input_ip_textEdit.setLineWrapColumnOrWidth(0)
self.input_ip_textEdit.setReadOnly(True)
self.input_ip_textEdit.setObjectName("input_ip_textEdit")
# 设置输出ip地址标签
self.output_ip_label = QtWidgets.QLabel(self.centralwidget)
self.output_ip_label.setGeometry(QtCore.QRect(270, 210, 71, 31))
font = QtGui.QFont()
font.setPointSize(12)
self.output_ip_label.setFont(font)
self.output_ip_label.setFocusPolicy(QtCore.Qt.NoFocus)
self.output_ip_label.setLayoutDirection(QtCore.Qt.LeftToRight)
self.output_ip_label.setTextFormat(QtCore.Qt.AutoText)
self.output_ip_label.setObjectName("output_ip_label")
# 设置输出ip栏
self.output_ip_textEdit = QtWidgets.QTextEdit(self.centralwidget)
self.output_ip_textEdit.setGeometry(QtCore.QRect(340, 60, 181, 341))
self.output_ip_textEdit.setReadOnly(True)
self.output_ip_textEdit.setObjectName("output_ip_textEdit")
# 设置进度
self.progressBar = QtWidgets.QProgressBar(self.centralwidget)
self.progressBar.setGeometry(QtCore.QRect(60, 470, 731, 23))
self.progressBar.setMinimum(0)
self.progressBar.setMaximum(100)
self.progressBar.setProperty("value", 0)
self.progressBar.setObjectName("progressBar")
self.timer = QBasicTimer()
self.timer.start(0, self)
# 设置进程标签
self.progress_label = QtWidgets.QLabel(self.centralwidget)
self.progress_label.setGeometry(QtCore.QRect(10, 465, 51, 31))
font = QtGui.QFont()
font.setPointSize(12)
self.progress_label.setFont(font)
self.progress_label.setObjectName("progress_label")
# 设置失败ip标签
self.fail_ip_label = QtWidgets.QLabel(self.centralwidget)
self.fail_ip_label.setGeometry(QtCore.QRect(530, 210, 71, 31))
font = QtGui.QFont()
font.setPointSize(12)
self.fail_ip_label.setFont(font)
self.fail_ip_label.setFocusPolicy(QtCore.Qt.NoFocus)
self.fail_ip_label.setLayoutDirection(QtCore.Qt.LeftToRight)
self.fail_ip_label.setTextFormat(QtCore.Qt.AutoText)
self.fail_ip_label.setObjectName("fail_ip_label")
# 设置失败ip栏
self.fail_ip_textEdit = QtWidgets.QTextEdit(self.centralwidget)
self.fail_ip_textEdit.setGeometry(QtCore.QRect(600, 60, 181, 341))
self.fail_ip_textEdit.setReadOnly(True)
self.fail_ip_textEdit.setObjectName("fail_ip_textEdit")
# 设置输入数的标签
self.input_num_label = QtWidgets.QLabel(self.centralwidget)
self.input_num_label.setGeometry(QtCore.QRect(180, 410, 41, 16))
self.input_num_label.setObjectName("input_num_label")
# 设置输入地址数的标签
self.input_ip_num_label = QtWidgets.QLabel(self.centralwidget)
self.input_ip_num_label.setGeometry(QtCore.QRect(230, 410, 31, 16))
self.input_ip_num_label.setObjectName("input_ip_num_label")
# 设置输出数的标签
self.output_ip_num_label = QtWidgets.QLabel(self.centralwidget)
self.output_ip_num_label.setGeometry(QtCore.QRect(490, 410, 31, 16))
self.output_ip_num_label.setObjectName("output_ip_num_label")
# 设置输出地址数的标签
self.output_num_label = QtWidgets.QLabel(self.centralwidget)
self.output_num_label.setGeometry(QtCore.QRect(440, 410, 41, 16))
self.output_num_label.setObjectName("output_num_label")
# 设置失败数的标签
self.fail_ip_num_label = QtWidgets.QLabel(self.centralwidget)
self.fail_ip_num_label.setGeometry(QtCore.QRect(750, 410, 31, 16))
self.fail_ip_num_label.setObjectName("fail_ip_num_label")
# 设置失败地址数的标签
self.fail_num_label = QtWidgets.QLabel(self.centralwidget)
self.fail_num_label.setGeometry(QtCore.QRect(700, 410, 41, 16))
self.fail_num_label.setObjectName("fail_num_label")
host_alive_MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(host_alive_MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 26))
self.menubar.setObjectName("menubar")
host_alive_MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(host_alive_MainWindow)
self.statusbar.setObjectName("statusbar")
host_alive_MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(host_alive_MainWindow)
QtCore.QMetaObject.connectSlotsByName(host_alive_MainWindow)
# 加载按钮函数
def on_click_load(self, event):
temp_address = self.ping_lineEdit.text()
self.address_res = []
self.address_fail = []
if temp_address not in self.address:
if self.input_ip_textEdit.toPlainText() == None:
self.input_ip_textEdit.setText(temp_address)
else:
self.input_ip_textEdit.append(temp_address)
self.address.append(temp_address)
else:
QMessageBox.information(self, '信息', '已自动去重!', QMessageBox.Ok, QMessageBox.Ok)
self.ping_lineEdit.clear()
self.flush_data()
# 加载文件按钮函数
def on_click_load_file(self, event):
file_path = easygui.fileopenbox(default='*.txt')
tab_num = 0
temp_lists = []
temp_address = ''
try:
with open(file_path) as old_file:
os.path.basename(file_path)
temp_address = old_file.read()
except:
pass
if "\r" in temp_address:
temp_lists = (temp_address.split("\r"))
elif "\n" in temp_address:
temp_lists = (temp_address.split("\n"))
elif temp_address == None:
return
else:
pass
for addre in temp_lists:
if addre not in self.address:
if self.input_ip_textEdit.toPlainText() == None:
self.input_ip_textEdit.setText(addre)
else:
self.input_ip_textEdit.append(addre)
self.address.append(addre)
else:
tab_num = tab_num + 1
if tab_num != 0:
QMessageBox.information(self, '信息', '已自动去重!', QMessageBox.Ok, QMessageBox.Ok)
self.flush_data()
# 清除按钮函数
def on_click_clear(self):
self.input_ip_textEdit.clear()
self.address = []
self.address_res = []
self.address_fail = []
# 进度条
def timerEvent(self, event):
step = self.count_num / self.total_num * 100
self.progressBar.setValue(step)
if step == 100:
self.timer.stop()
# 开始探测按钮函数
def on_click_action(self, event):
self.output_ip_textEdit.clear()
self.fail_ip_textEdit.clear()
thread_num = self.thread_spinBox.text()
for address in self.address:
self.count_num = self.count_num + 1
pinger_value = pinger.Pinger()
flag = pinger_value.verbose_ping(dest_addr=address)
if flag == True:
self.success_num = self.success_num + 1
if self.output_ip_textEdit.toPlainText() == None:
self.output_ip_textEdit.setText(address)
else:
self.output_ip_textEdit.append(address)
self.address_res.append(address)
self.output_ip_textEdit.update()
else:
self.fail_num = self.fail_num + 1
if self.fail_ip_textEdit.toPlainText() == None:
self.fail_ip_textEdit.setText(address)
else:
self.fail_ip_textEdit.append(address)
self.address_fail.append(address)
self.fail_ip_textEdit.update()
QApplication.processEvents() # 逐步打印
self.flush_data()
# 输出成文件函数
def on_click_output_value(self, event):
file = open('address.txt', mode='a')
for address_value in self.address_res:
file.write(address_value + "\n")
file.close()
QMessageBox.information(self, '信息', '已在当前文件夹生成address.txt文件!', QMessageBox.Ok, QMessageBox.Ok)
def flush_data(self):
self.total_num = len(self.address)
self.input_ip_num_label.setText(str(self.total_num))
self.input_ip_num_label.update()
self.output_ip_num_label.setText(str(len(self.address_res)))
self.output_ip_num_label.update()
self.fail_ip_num_label.setText(str(len(self.address_fail)))
self.fail_ip_num_label.update()
# 自动生成----控件的初始化值
def retranslateUi(self, host_alive_MainWindow):
_translate = QtCore.QCoreApplication.translate
host_alive_MainWindow.setWindowTitle(_translate("host_alive_MainWindow", "主机存活探测工具 --by zichen"))
self.ping_label.setText(_translate("host_alive_MainWindow", "Ping:"))
self.load_Button.setText(_translate("host_alive_MainWindow", "加载"))
self.loadfile_Button.setText(_translate("host_alive_MainWindow", "导入文件"))
self.clear_Button.setText(_translate("host_alive_MainWindow", "清除"))
self.thread_label.setText(_translate("host_alive_MainWindow", "线程数:"))
self.action_Button.setText(_translate("host_alive_MainWindow", "开始探测"))
self.output_value_Button.setText(_translate("host_alive_MainWindow", "导出结果"))
self.input_ip_label.setText(_translate("host_alive_MainWindow", "输入栏"))
self.output_ip_label.setText(_translate("host_alive_MainWindow", "输出栏"))
self.progress_label.setText(_translate("host_alive_MainWindow", "进度:"))
self.fail_ip_label.setText(_translate("host_alive_MainWindow", "失败栏"))
self.input_num_label.setText(_translate("host_alive_MainWindow", "数目:"))
self.input_ip_num_label.setText(_translate("host_alive_MainWindow", "0"))
self.output_ip_num_label.setText(_translate("host_alive_MainWindow", "0"))
self.output_num_label.setText(_translate("host_alive_MainWindow", "数目:"))
self.fail_ip_num_label.setText(_translate("host_alive_MainWindow", "0"))
self.fail_num_label.setText(_translate("host_alive_MainWindow", "数目:"))
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_host_alive_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
外部引用的pinger类
# !coding=utf-8
# by kyan001
import sys
import socket
import struct
import select
import time
import threading
__version__ = "1.4.1"
if sys.platform == "win32":
# On Windows, the best timer is time.clock()
default_timer = time.perf_counter
else:
# On most other platforms the best timer is time.time()
default_timer = time.time
# From /usr/include/linux/icmp.h; your milage may vary.
ICMP_ECHO_REQUEST = 8 # Seems to be the same on Solaris.
class Pinger(object):
def checksum(self, source_string):
"""
I'm not too confident that this is right but testing seems
to suggest that it gives the same answers as in_cksum in ping.c
"""
sum = 0
countTo = len(source_string)
count = 0
while count < countTo:
thisVal = source_string[count + 1] * 256 + source_string[count]
sum = sum + thisVal
count = count + 2
if countTo < len(source_string):
sum = sum + ord(source_string[len(source_string) - 1])
sum = (sum >> 16) + (sum & 0xffff)
sum = sum + (sum >> 16)
answer = ~sum
answer = answer & 0xffff
# Swap bytes. Bugger me if I know why.
answer = answer >> 8 | (answer << 8 & 0xff00)
return answer
def receive_one_ping(self, my_socket, ID, timeout):
"""
receive the ping from the socket.
"""
timeLeft = timeout
while True:
startedSelect = default_timer()
whatReady = select.select([my_socket], [], [], timeLeft)
howLongInSelect = (default_timer() - startedSelect)
if whatReady[0] == []: # Timeout
return
timeReceived = default_timer()
recPacket, addr = my_socket.recvfrom(1024)
icmpHeader = recPacket[20:28]
type, code, checksum, packetID, sequence = struct.unpack(
"bbHHh", icmpHeader
)
# Filters out the echo request itself.
# This can be tested by pinging 127.0.0.1
# You'll see your own request
if type != 8 and packetID == ID:
bytesInDouble = struct.calcsize("d")
timeSent = struct.unpack("d", recPacket[28:28 + bytesInDouble])[0]
return timeReceived - timeSent
timeLeft = timeLeft - howLongInSelect
if timeLeft <= 0:
return
def send_one_ping(self, my_socket, dest_addr, ID):
"""
Send one ping to the given >dest_addr<.
"""
dest_addr = socket.gethostbyname(dest_addr)
# Header is type (8), code (8), checksum (16), id (16), sequence (16)
my_checksum = 0
# Make a dummy header with a 0 checksum.
# ID: Low-endian identifier, bbHHh: network byte order
header = struct.pack("bbHHh", ICMP_ECHO_REQUEST, 0, my_checksum, ID, 1)
bytesInDouble = struct.calcsize("d")
data = (192 - bytesInDouble) * "Q"
data = struct.pack("d", default_timer()) + data.encode()
# Calculate the checksum on the data and the dummy header.
my_checksum = self.checksum(header + data)
# Now that we have the right checksum, we put that in. It's just easier
# to make up a new header than to stuff it into the dummy.
header = struct.pack("bbHHh", ICMP_ECHO_REQUEST, 0, socket.htons(my_checksum), ID, 1)
packet = header + data
my_socket.sendto(packet, (dest_addr, 1)) # Don't know about the 1
def ping(self, dest_addr, timeout=0.5, unit="s", src_addr=None, ttl=64):
"""
Send one ping to destination address with the given timeout.
Args:
dest_addr: Str. The destination address. Ex. "192.168.1.1"/"example.com"
timeout: Int. Timeout in seconds. Default is 4s, same as Windows CMD.
unit: Str. The unit of returned value. Default is "s" for seconds, "ms" for milliseconds.
src_addr: Str. The IP address to ping from. Ex. "192.168.1.20"
ttl: Int. The Time-To-Live of the outgoing packet. Default is 64, same as in Linux and macOS.
Returns:
The delay in seconds/milliseconds or None on timeout.
"""
my_socket = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP)
my_socket.setsockopt(socket.SOL_IP, socket.IP_TTL, ttl)
if src_addr:
my_socket.bind((src_addr, 0))
my_ID = threading.current_thread().ident & 0xFFFF
self.send_one_ping(my_socket, dest_addr, my_ID)
delay = self.receive_one_ping(my_socket, my_ID, timeout) # in seconds
my_socket.close()
if delay is None:
return None
if unit == "ms":
delay *= 1000 # in milliseconds
return delay
def verbose_ping(self, dest_addr, count=1, *args, **kwargs):
"""
Send pings to destination address with the given timeout and display the result.
Args:
dest_addr: Str. The destination address. Ex. "192.168.1.1"/"example.com"
count: Int. How many pings should be sent. Default is 4, same as Windows CMD.
*: And all the other arguments available in ping().
Returns:
Formatted ping results printed.
"""
timeout = kwargs.get("timeout")
src_addr = kwargs.get("src_addr")
unit = kwargs.setdefault("unit", "ms")
for i in range(count):
output_text = "ping '{}'".format(dest_addr)
output_text += " from '{}'".format(src_addr) if src_addr else ""
output_text += " ... "
print(output_text, end="")
try:
delay = self.ping(dest_addr, *args, **kwargs)
except socket.gaierror as e:
# print("Failed. (socket error: '{}')".format(e))
return False
break
if delay is None:
# print("Timeout > {}s".format(timeout) if timeout else "Timeout")
return False
else:
# print("{value}{unit}".format(value=int(delay), unit=unit))
return True
print()
该类是来源于github上的kyan001编写的,这里日常感谢一下,之前的stock编程我就没用了,我用了python自带的python2转python3工具转换后,有问题,我就干脆在github另找一个,修改了一下,原来的代码如下:https://github.com/kyan001/ping3
多线程问题
这里并没有使用多线程,因为qt对threading不支持,它有自带的多线程Qthread,这个坑,困扰我一天(因为这个没报错,主窗口动不动就退出,debug也没用看出什么问题).我就不打算用多线程了,等以后再把坑填上
福利
知乎学习pyqt5:https://zhuanlan.zhihu.com/xdbcb8?utm_source=wechat_session&utm_medium=social&from=singlemessage