Qt实现端口扫描器
首先展示一下效果:
界面通过Qt设计师做出来的。
主要有两个类。
首先主函数:
#include "mainwindow.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; w.show(); return a.exec(); }
实现UI循环。
第一个类,主窗体类:
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <QString> #include <QDebug> #include <QTcpSocket> #include "scanner.h" namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); bool checkip(QString ip); void startscanner(QString ip,int startport,int endport); ~MainWindow(); private slots: void on_pushButton_clicked();//开始扫描 void setBar(int value);//修改进度条 void on_pushButton_2_clicked();//暂停 void on_pushButton_3_clicked();//终止 private: Ui::MainWindow *ui; Scanner *scanner; bool threadisrunnig; }; #endif // MAINWINDOW_H
因为是用的Qt设计师,所以函数名有点挫。
然后是扫描线程类,用来扫描端口:
#ifndef SCANNER_H #define SCANNER_H #include<QThread> class Scanner:public QThread { Q_OBJECT public: Scanner(); void run();//不多说,自己Google void stop();//实现线程安全停止,用Terminate是不安全的 signals: sentnowport(int value);//更新进度条 private: volatile bool stopped; }; #endif // SCANNER_H
类实现:

#include "mainwindow.h" #include "ui_mainwindow.h" #include<QMutex> #include<QThread> #include<QProgressBar> #include <QGraphicsItem> QMutex percent; QMutex mutex; QMutex text; int nowport; int staport; int endport; QString ip; QTextEdit *result; Scanner::Scanner() { stopped=false; } void Scanner::run() { while(!stopped) { if(nowport>endport) { break; } mutex.lock(); int tmpport=nowport++; mutex.unlock(); emit sentnowport(nowport); QTcpSocket socket(0); socket.abort(); socket.connectToHost(ip,tmpport); if(socket.waitForConnected(1000)) { //qDebug()<<"connect"; text.lock(); QString message=""; message+=QString::number(tmpport,10)+" opened!"; result->append(message); text.unlock(); //qDebug()<<"connect over"; } else ;//qDebug()<<tmpport<<"not open"<<endl; } stopped=false; } void Scanner::stop() { stopped=true; } MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); ui->pushButton_2->setVisible(false); threadisrunnig=false; } MainWindow::~MainWindow() { delete ui; } void MainWindow::setBar(int value) { //qDebug()<<value; ui->progressBar->setValue(value); } bool MainWindow::checkip(QString ip) { QRegExp rx2("\\d+\\.\\d+\\.\\d+\\.\\d+"); if( !rx2.exactMatch(ip) ) { return false; } //qDebug()<<"check true"; return true; } void MainWindow::on_pushButton_clicked() { QString desip=ui->lineEdit->text(); ui->progressBar->setValue(0); ui->pushButton_2->setText("暂停"); //qDebug()<<desip; if(!checkip(desip)) { ui->lineEdit->setText("ip 地址错误"); } else { //ui->progressBar->setRange(0,0); ip=desip; staport=ui->spinBox->value(); endport=ui->spinBox_2->value(); nowport=staport; result=ui->textEdit; result->clear(); //qDebug()<<staport<<endport<<nowport; int num=ui->spinBox_3->value(); scanner=new Scanner[num]; ui->progressBar->setRange(staport,endport); ui->pushButton_2->setVisible(true); for(int i=0;i<num;i++) { scanner[i].start(); threadisrunnig=true; connect(scanner+i,SIGNAL(sentnowport(int)),this,SLOT(setBar(int))); } } } void MainWindow::startscanner(QString ip, int startport, int endport) { if(startport>endport) { int tmp=startport; startport=endport; endport=tmp; } QTcpSocket socket(0); for(int i=startport;i<=endport;i++) { socket.abort(); socket.connectToHost(ip,i); if(socket.waitForConnected(1000)) qDebug()<<i<<"connected!"; } } void MainWindow::on_pushButton_2_clicked() { if(ui->pushButton_2->text()=="暂停") { bool couldPause=false; for(int i=0;i<ui->spinBox_3->value();i++) if(threadisrunnig&&scanner[i].isRunning()) couldPause=true; if(!couldPause) return; ui->pushButton_2->setText("继续"); mutex.lock(); } else { ui->pushButton_2->setText("暂停"); mutex.unlock(); } } void MainWindow::on_pushButton_3_clicked() { ui->progressBar->setValue(endport); ui->pushButton_2->setVisible(false); if(!threadisrunnig) return; for(int i=0;i<ui->spinBox_3->value();i++) scanner[i].stop(); delete(scanner); }
解释一下:
有三个互斥访问变量:当前任务端口nowport, 扫描结果 textEdit,进度条 progressBar。
在访问这三个变量的时候要用信号量实现互斥访问。
by nianhao@ouc,万一被查重了不负责。。
更新一波,增加网段扫描
首先是ip遍历函数:

int ip2num(QString ip) { bool ok; int lp[4]; QStringList iplist=ip.split('.'); for (int i=0;i<iplist.length();i++) lp[i]=iplist[i].toInt(&ok,10); return lp[0] << 24 | lp[1] << 16 | lp[2] << 8 | lp[3]; } QString num2ip(int num)//:# int num to ip { int ip[4]; ip[3] = (num & 0xff); ip[2] = (num & 0xff00) >> 8; ip[1] = (num & 0xff0000) >> 16; ip[0] = (num & 0xff000000) >> 24; QString rip=QString("%1").arg(ip[0])+QString(".")+QString("%1").arg(ip[1])+QString(".")+QString("%1").arg(ip[2])+QString(".")+QString("%1").arg(ip[3]); return rip; } bool iprange(QString ip1,QString ip2) { int num1 = ip2num(ip1); int num2 = ip2num(ip2); sip=num1; eip=num2; int tmp = num2 - num1; if(tmp < 0) return false; else return true; }
通过位运算遍历ip地址。
然后我们修改一下run函数,给线程分配任务时同时给定ip,这样实现ip的遍历void Scanner::run()
{ while(!stopped) { mutex.lock(); QString tmpIp=nowIp;
if(nowport>endport||nip>eip) { if(nip>eip) { mutex.unlock(); emit sentnowport(endport); break; } nip++; emit sentnowip(nip); nowIp=num2ip(nip); QString msg=QString("now the scanning ip is %1").arg(nowIp); if(nip<=eip) result->append(msg); nowport=staport; } int tmpport=nowport++; //发出更新进度条信号 emit sentnowport(nowport); mutex.unlock(); //尝试tcp连接 QTcpSocket socket(0); socket.abort(); socket.connectToHost(tmpIp,tmpport); if(socket.waitForConnected(1000)) { //qDebug()<<"connect"; text.lock(); QString message=""; message+=QString::number(tmpport,10)+" opened!"; result->append(message); text.unlock(); //qDebug()<<"connect over"; } else ;//qDebug()<<tmpport<<"not open"<<endl; } stopped=false; }
最后修改一下界面文件,增加一个指示全局进度的进度条。
最终效果:
这样就完成了网络安全的实验了。
整个项目的源代码:点击这里
密码:w1lh
大家好好复习欢迎给我发期末重点啊,赠人玫瑰~~~香的不行
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 字符编码:从基础到乱码解决