传送门
本系列原创博文传送门:
本章目标
本章的目标是优化,暂时发现的问题有以下几个:
1、点击启动后,工具会卡死,直到结果出来
2、结果还不能输出到大编辑框内
3、编辑框的复制功能尚未实现
4、不能显示工具当前运行状态,执行中和待命
暂时就想到这四个问题,先将这四个问题解决了,再通过体验来看看哪些地方可以优化。
步骤实施
第一步,解决启动后工具卡死的问题。
工具之所以卡死,有两个原因:
一个是按钮响应函数直接调用了遍历逻辑代码,是实时等待;另外一个是,并发的线程数对于我这台联想老笔记本可能有些压力过大,运行几遍之后,电脑的一些图标都显示不出来了。
第一个原因,就是采用异步调用,做法如下:
1、按钮响应函数A异步调用 PortSearchGUI.py 另外一个函数 B
2、按钮响应函数A,将启动按钮设置为不可用,设置窗口标题显示出类似 运行中 的信息
3、函数B接收到最终结果后,将结果输出到大编辑框中,恢复启动按钮的状态和窗口标题文字
接下来开始实施。
引入线程模块:
import threading
新建逻辑调用函数B,并修改相应函数A,顺带修改默认的并发数为300:
# 函数B 负责调用逻辑
def logic(ip, thread_line, port_start, port_end):
search = PortSearch(ip=ip, thread_line=thread_line, port_start=port_start, port_end=port_end)
result = search.run()
print(type(result))
print(result)
# string = json.dumps(result)
# report_box_edit.setPlainText(string)
start_btn.setEnabled(True)
window.setWindowTitle('端口嗅探器 v1.0')
@Slot()
def collect_data():
ip = ip_line_edit.text()
thread_line = int(thread_line_edit.text())
port_start = int(port_line_edit1.text())
port_end = int(port_line_edit2.text())
if not ip:
show_tip(MESSAGE[0])
return
if thread_line < 1:
show_tip(MESSAGE[1])
return
if port_start < 0:
show_tip(MESSAGE[2])
return
if port_end <= port_start:
show_tip(MESSAGE[3])
return
thread = threading.Thread(target=logic, args=(ip, thread_line, port_start, port_end))
thread.start() # 异步调用,避免工具卡死
start_btn.setEnabled(False) # 限制按钮,避免重复调用
window.setWindowTitle('端口嗅探器 v1.0 ---- 执行中')
运行一下看看。
运行时:
运行后:
输出结果:
<class 'list'>
[['www.jianbing.com', 80, 0, b''], ['www.jianbing.com', 443, 0, b'']]
运行期间,工具可以移动和正常操作,电脑明显没有之前卡顿,遍历时间也没有明显增加。那么第一个问题和第四个问题就算解决了。
然后解决第二个问题,就是将这个list内容,输出到大编辑框内:
# 函数B 负责调用逻辑
def logic(ip, thread_line, port_start, port_end):
search = PortSearch(ip=ip, thread_line=thread_line, port_start=port_start, port_end=port_end)
result = search.run()
print(type(result))
print(result)
string = ''
str_len = len(result)
report_box_edit.setPlainText('')
if str_len > 0: # 处理返回数据,输出到编辑框内
for ele in result:
# string = string + '端口:' + str(ele[1]) + ' ,状态:开启, 输出信息:' + str(ele[3]) + '</p><p>'
report_box_edit.appendPlainText('端口:' + str(ele[1]) + ' ,状态:开启, 输出信息:' + str(ele[3])) # 逐条添加信息
else:
string = '所有端口均未开启'
report_box_edit.setPlainText(string)
start_btn.setEnabled(True)
window.setWindowTitle('端口嗅探器 v1.0')
运行效果图:
这样,就算解决了第二个问题了。
现在只剩下第三个问题,即复制功能。
首先安装剪贴板模块:
pip install pyperclip --user
模块很小,安装成功。
引入模块:
import pyperclip
声明全局变量:
G_LIST = ['', '']
添加提示语:
MESSAGE = (
'ip或者网址不得为空',
'并发数不得小于1',
'开始端口号不得小于0',
'结束端口号需要大于开始端口号',
'原文复制成功'
)
新建槽函数,作为复制按钮的响应函数:
@Slot()
def copy():
pyperclip.copy(G_LIST[0])
show_tip(MESSAGE[4])
建立连接:
copy_ori_btn = QPushButton() # 修改父类
copy_ori_btn.setText('复制原文')
copy_ori_btn.clicked.connect(copy) # 建立连接
测试一下,点击之后,
随便打开一个qq窗口,ctrl+v,发现成功复制,多粘贴几次,就是下图的效果:
结语
至此,本章开头设立的四个问题,全部都解决了。
工具已经越来越完善了。
下一章,将继续完善该工具,主要方向是根据端口来推测出该端口的常见运行服务。
然后顺带完善其他小功能,比如复制全文按钮的功能和清空按钮的功能。