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);
}
View Code

解释一下:

有三个互斥访问变量:当前任务端口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;
}
View Code

通过位运算遍历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

大家好好复习欢迎给我发期末重点啊,赠人玫瑰~~~香的不行

原文地址:https://www.cnblogs.com/superxuezhazha/p/6208708.html