Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Multithreaded proxy checker GUI program with Qt (need help with QNetworkAccessManager & threads)



  • Hello!

    I am trying to make a simple multithreaded GUI program that goes throught a list of proxies and
    for each proxy it check A) SSL support and B) anonymous support and then prints the data to
    QTreeWidget with each row containing proxy IP:port, if proxy supports SSL and if it is anonymous proxy.
    Like this:

    192.111.213.223:8080 Yes Yes
    143.123.123.123:3128 Yes No
    etc....

    What I want the program to do is:

    1. create two or more threads and for each thread create QNetworkAccessManager object.

    2. each thread goes throught the list of proxies (just a simple QList now),
      checking if the proxy has SSL support (by setting QNAM proxy and trying to connect to
      https://encrypted.google.com) and anonymous support (by setting QNAM proxy and then trying
      to connect to some IP showing web site and parse the result).

    3. threads should be synchronized so that they don't step over each others toes and never
      try to check the same proxy from the list (that is each proxy in that list is checked only once by one
      of the threads).

    4. each time one of threads has successfully determined both SSL and anonymous support it will then send data (with signal) to main GUI thread for printing to some graphical widget (like QTreeWidget in this example) and then continue to next proxy in the list so long untill there is no more proxies left for checking in the list.

    I believe that QStringList as an argument for signal would be good for this ?
    Like: void dataReady(const QStringList& data)
    and then in thread code something like this ?:

    QStringList data;
    data << proxyIP << (proxySSLsupport ? "Yes" : "No") << (proxyAnonymousSupport ? "Yes" : "No");
    emit dataReady(data);

    1. after all proxies have been checked a signal is sent to notify main GUI thread.

    Can someone please show how to do this right? How to synchronize QNetworkAccessManager so that each thread fires up signal and sends ready data (proxy IP, SSL support and Anonymous support)

    I am not thread expert and only know basics of signal & slots of Qt.
    This is really driving me crazy

    Here's my nonworking, incomplete code.

    mainwindow.h

    @#include "worker.h"

    static const int NUMBER_OF_THREADS = 2;

    class MainWindow : public QMainWindow
    {
    Q_OBJECT
    public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    private slots:
    void on_pushButton_clicked();
    private:
    Ui::MainWindow ui;
    QThread
    t[NUMBER_OF_THREADS];
    };

    @
    mainwindow.cpp

    @#include "mainwindow.h"
    #include "worker.h"

    QList<QString> Worker::proxyList; /* proxyList shared by threads /
    int Worker::n = 0; /
    proxyList counter to keep track of current proxy */

    MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
    {
    ui->setupUi(this);

    for(int i = 0;i < NUMBER_OF_THREADS;i++) {
        t[i] = new QThread;
        Worker*  worker = new Worker;
        worker->moveToThread(t[i]);
    
        /* Do the actual proxy checking stuff in doProxyCheck() SLOT */
        connect(t[i], SIGNAL(started()), worker,SLOT(doProxyCheck()));
    
        /* Cleanup stuff for both thread & worker */
        connect(worker, SIGNAL(finished()), t[i], SLOT(quit()));
        connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
        connect(t[i], SIGNAL(finished()), t[i], SLOT(deleteLater()));
    }
    
    /* Here just fill the proxyList shared by all workers */
    Worker::proxyList.append("88.85.120.36:80");
    Worker::proxyList.append("87.252.227.135:3128");
    Worker::proxyList.append("87.229.210.30:3128");
    /* etc ...... */
    

    }

    void MainWindow::on_pushButton_clicked()
    {
    Worker::n = 0;
    for(int i = 0;i < NUMBER_OF_THREADS;i++) {
    t[i]->start();
    }
    }

    @
    worker.h

    @#include <QDebug>
    #include <QThread>
    #include <QNetworkAccessManager>
    #include <QNetworkProxy>

    class Worker : public QObject
    {
    Q_OBJECT
    public:
    static QList<QString> proxyList;
    static int n;
    signals:
    void finished();
    public slots:
    void encryptedSlot(QNetworkReply*) {
    qDebug() << "Yes";
    }

    void    checkSSL(QString host)
    {
        /* Split the IP:port format to separate host & port part */
        QStringList url = host.split(":");
        qDebug() << url.at(0) << ":" << url.at(1);
    
        QNetworkProxy   proxy(QNetworkProxy::HttpProxy,url.at(0),url.at(1).toUInt());
        this->man->setProxy(proxy);
        this->man->connectToHost("encrypted.google.com",443);
    }
    void    checkAnonymous(QString host)
    {
        /* Do similar thing here like with checkSSL() with
         * the only exception that instead of encrypted.google.com
         * we try to connect throught proxy to some IP address showing
         * web page (like whatismyip.org) and parse the result.
         * If the IP reported is the same as the proxy IP just set
         * then it's anonymous proxy */
        /* Split the IP:port format to separate host & port part */
        QStringList url = host.split(":");
        qDebug() << url.at(0) << ":" << url.at(1);
    
        QNetworkProxy   proxy(QNetworkProxy::HttpProxy,url.at(0),url.at(1).toUInt());
        this->man->setProxy(proxy);
       this->man->get(QUrl("http://www.whatismyip.com");
    
    }
    void    doProxyCheck() {
    
        this->man = new QNetworkAccessManager;
       /* How to handle QNetworkAccessManager signals in threads ???? */
    
        while(n < Worker::proxyList.count()) {
            qDebug() << "Thread # " << QThread::currentThreadId() << " checking proxy " << Worker::proxyList.at(n) << " SSL support";
            this->checkSSL(Worker::proxyList.at(n));
            qDebug() << "Thread # " << QThread::currentThreadId() << " checking proxy " << Worker::proxyList.at(n) << " Anonymous support";
            this->checkAnonymous(Worker::proxyList.at(n));
            n++;
        }
    }
    

    private:
    QNetworkAccessManager* man;
    };
    @


Log in to reply