频道栏目
首页 > 程序开发 > Web开发 > Python > 正文
基于PyQt5制作的端口扫描器
2018-01-02 11:33:35      个评论    来源:qq_35887983的博客  
收藏   我要投稿

由于课设的关系,选择用PyQt5制作一个端口扫描器。期间遇到了许多问题,在此回忆总结一下

操作系统:Windows 10 1709

python版本:python 3.5.3

注:本文所述方法大部分为摸索制作过程中搜索总结而来,本文只是进行归纳汇总

一,Python-socket

判断一个端口是否开放的方法有很多,最简单的自然是建立TCP三次握手,也就是简单的connect

s = socket(AF_INET,SOCK_STREAM)
s.connect((self.host,self.port))
s.close()

用try包裹一下,做一下错误判定

except timeout:#超时,一般就认为端口为关闭,如果超时时间设置过小可能会造成遗漏
      s.close()
      return
except ConnectionRefusedError:#连接被拒绝
      s.close()
      return
except OSError as e:#其它的一些错误,当端口为0的时候会触发,还有就是linux系统中连接有上限,过了上限会报【OSERROR ERROR 24】
      if self.port!=0:
           print("OSError",self.port,self.host,e)
      return
except Exception as e:#防患于未然
      print(repr(e),self.port,self.host)
      return
本来还想尝试一下raw_socket,只建立TCP第一次握手,发SYN包,但是遇到了一些问题

raw_socket需要手动制作TCP头部和IP头部

tcp_header=Create_TCP_SYN_Header("10.241.65.141","10.241.65.1",22)
ip_header=CreateIPHeaders("10.241.65.141","10.241.65.1")
具体实现可以百度,有很多

然后就是建立这个RAW_SOCKET,一定要用管理员权限

网上有两种写法

s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_TCP)
前者发包的时候会把我写好的头当作数据发出去

\

后者直接报错

\

弄了好多小时也无解,故放弃

后来学长说python的socket库不完整。。可能是某些原因吧

二,PyQt5

这是第三个用pyqt写的程序了,然而才发现designer这个好东西,直接画界面就好了

界面的第一版不怎么好看,第二版算是正式版

\

想想遇到的坑吧。。

将滚动条直接滚到底部,这么一个小功能还是找了好久

self.listView.verticalScrollBar().setValue(self.listView.verticalScrollBar().maximum())
设置文本输入格式和范围,网上有其它类型的
self.lineEdit.setValidator(QtGui.QIntValidator(1,50000))
一组按钮可以设置号每个按钮的id,然后获取选择id来实时获取当前选项
self.buttonGroup.setId(self.ip_radio,1)
self.buttonGroup.setId(self.port_radio,0)
if self.buttonGroup.checkedId():
    self.list_by_ip()
else:
    self.list_by_port()
设置QTreeWidget宽度
self.result_tree.setColumnWidth(0,250)#第一列设成250
从QlistWidget移除选中的一行(self.ippool为QlistWidget)
self.ippool.removeItemWidget(self.ippool.takeItem(self.ippool.row(self.ippool.selectedItems()[0])))
为QTreeWidgetItem设置复选框
temp=QtWidgets.QTreeWidgetItem(self.result_tree.topLevelItem(item))
temp.setFlags(temp.flags() | Qt.ItemIsUserCheckable)
temp.setCheckState(0, Qt.Unchecked)
隐藏一个QTreeWidgetItem

self.item.setHidden(True)

差不多就这些

图标很多,颜色随心

最后,pyqt5的打包使用python 3.6.4 pyinstaller在windows10 32位 的虚拟机中直接打包的,直接

pyinstaller -F -w -i scan.ico scanner.py
就可以,python3.5下的pyinstaller打包不全PyQt5,32位则是希望打包后的文件可以在32和64位系统中运行

三,线程

端口扫描器肯定是要多线程的啦

这次设计的是主界面按下按钮后,开启一个Qthread进行创建子线程操作,循环创建,设定同时运行的线程数上限,利用一些信号支持用户的手动停止

期间的问题就是,如果Qthread在执行的过程中更改了主线程的属性或内容,会造成python的不稳定,很容易直接崩溃并且无任何明显报错,唯一出现的可能是

QWidget::repaint: Recursive repaint detected

这句报错只有在控制台窗口下才会出现,IDLE并不会打印

可以利用信号(pysignal)或者其它机制避免Qthread更改主线程的属性或内容

PS:这里的不稳定十分的玄学,在某些时候直接崩溃,IDLE无任何报错,即使全部用try包裹也没用。甚至一些print语句也会影响到其崩溃是否发生,总之感觉程序处于一种极其不稳定的状态,所以据说好像QT作者并不推荐Qthread

pps:好像在IDLE下不那么容易崩溃

另外,python自带的threading不会有这个问题,不过得用好线程锁,这里就不细说了

点击复制链接 与好友分享!回本站首页
上一篇:Python通过socket来实现一个写日志的程序
下一篇:数据分析:numpy
相关文章
图文推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站