Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. How to Scan Ports with TCP Client ?
QtWS25 Last Chance

How to Scan Ports with TCP Client ?

Scheduled Pinned Locked Moved Unsolved General and Desktop
tcpscannerport
2 Posts 2 Posters 556 Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • T Offline
    T Offline
    TokaraForest
    wrote on 13 Jun 2023, 10:29 last edited by TokaraForest
    #1

    Hi,

    I have a TCP Client GUI application that sends read requests periodically once it connects to server side. For now, client and server side runs on my pc and I use my local address. I have followed and edited my application according to Fortune Client Example.There are two push buttons. First one scans available ip addresses and the other one connects to server after I write Port value on a linedit and select ip address on comboBox. Here my code so far:

    widget.h:

    #ifndef WIDGET_H
    #define WIDGET_H
    
    #include <QWidget>
    #include <QAbstractSocket>
    #include <QDebug>
    #include <QHostAddress>
    #include <QMessageBox>
    #include <QString>
    #include <QTcpSocket>
    #include <QHostInfo>
    #include <QNetworkInterface>
    
    
    QT_BEGIN_NAMESPACE
    namespace Ui { class Widget; }
    QT_END_NAMESPACE
    
    class Widget : public QWidget
    {
        Q_OBJECT
    
    public:
        Widget(QWidget *parent = nullptr);
        ~Widget();
    
    private slots:
        void readSocket();
    
        void discardSocket();
    
        void displayError(QAbstractSocket::SocketError socketError);
    
        void on_pushButtonConnect_clicked();
    
        void connected();
    
        void enablePushButtonConnectButton();
    
        void on_pushButtonScan_clicked();
    
    private:
        Ui::Widget *ui;
    
        QTcpSocket *tcpSocket = nullptr;
    };
    #endif // WIDGET_H
    
    

    widget.cpp:

    #include "widget.h"
    #include "ui_widget.h"
    
    Widget::Widget(QWidget *parent)
        : QWidget(parent)
        , ui(new Ui::Widget)
    {
        ui->setupUi(this);
    
        tcpSocket = new QTcpSocket(this);
    
        ui->pushButtonConnect->setDefault(true);
        ui->pushButtonConnect->setEnabled(false);
    
        connect(ui->comboBoxServerName, &QComboBox::editTextChanged,
                this, &Widget::enablePushButtonConnectButton);
        connect(ui->lineEditServerPort, &QLineEdit::textChanged,
                this, &Widget::enablePushButtonConnectButton);
        connect(tcpSocket, &QTcpSocket::connected,
                this, &Widget::connected);
        connect(tcpSocket, &QTcpSocket::readyRead,
                this, &Widget::readSocket);
        connect(tcpSocket, &QAbstractSocket::errorOccurred,
                this, &Widget::displayError);
    }
    
    Widget::~Widget()
    {
        delete ui;
    }
    
    void Widget::readSocket()
    {
        QByteArray buffer;
    
        buffer = tcpSocket->readAll();
    
        qDebug() << buffer;
    }
    
    void Widget::displayError(QAbstractSocket::SocketError socketError)
    {
        switch (socketError) {
            case QAbstractSocket::RemoteHostClosedError:
            break;
            case QAbstractSocket::HostNotFoundError:
                QMessageBox::information(this, "QTCPClient", "The host was not found. Please check the host name and port settings.");
            break;
            case QAbstractSocket::ConnectionRefusedError:
                QMessageBox::information(this, "QTCPClient", "The connection was refused by the peer. Make sure QTCPServer is running, and check that the host name and port settings are correct.");
            break;
            default:
                QMessageBox::information(this, "QTCPClient", QString("The following error occurred: %1.").arg(tcpSocket->errorString()));
            break;
        }
    }
    
    void Widget::on_pushButtonConnect_clicked()
    {
        ui->pushButtonConnect->setEnabled(false);
        tcpSocket->abort();
    
        tcpSocket->connectToHost(ui->comboBoxServerName->currentText(),
                                 ui->lineEditServerPort->text().toInt());
    }
    
    void Widget::connected()
    {
        qDebug() << "connected";
    }
    
    void Widget::enablePushButtonConnectButton()
    {
        ui->pushButtonConnect->setEnabled(!ui->comboBoxServerName->currentText().isEmpty() &&
                                     !ui->lineEditServerPort->text().isEmpty());
    }
    
    void Widget::on_pushButtonScan_clicked()
    {
        ui->comboBoxServerName->setEditable(true);
        QString name = QHostInfo::localHostName();
        if (!name.isEmpty()) {
            ui->comboBoxServerName->addItem(name);
            QString domain = QHostInfo::localDomainName();
            if (!domain.isEmpty())
                ui->comboBoxServerName->addItem(name + QChar('.') + domain);
        }
    
        if (name != QLatin1String("localhost"))
            ui->comboBoxServerName->addItem(QString("localhost"));
        // find out IP addresses of this machine
        QList<QHostAddress> ipAddressesList = QNetworkInterface::allAddresses();
        // add non-localhost addresses
        for (int i = 0; i < ipAddressesList.size(); ++i) {
            if (!ipAddressesList.at(i).isLoopback())
                ui->comboBoxServerName->addItem(ipAddressesList.at(i).toString());
        }
        // add localhost addresses
        for (int i = 0; i < ipAddressesList.size(); ++i) {
            if (ipAddressesList.at(i).isLoopback())
                ui->comboBoxServerName->addItem(ipAddressesList.at(i).toString());
        }
    }
    
    

    Now I want to scan ports between 1500-1600 with scan button and see available port values on comboBox. Then I can connect a server with fixed ip address and port value selected on comboBox.
    When I enter wrong port value on linedit, client tries to connect for a while then shows error message. If I try to connect available ports between 1500-1600 in a for loop, it will take time. Also I don't think this is the way.
    There is Blocking Fortune Client example that has synchronous approach. This example uses waitFor....() functions in a non-GUI thread as I understand.
    So do I change my client application's asynchronous approach to syncronous approach ? Would it be the appropriate way with Blocking Fortune example to scan ports by writing something like this ?:

    quint16 start = 1500;
    quint16 end = 1600;
    quint16 timeoutInt = 50;
    
    for(quint16 i = start; i < end; i++){
                tcpSocket.connectToHost(host, i);
                if(tcpSocket.waitForConnected(timeoutInt)){
                    qInfo() << "Open Port: " << i;
                    QString openPort = QString::number(i);
                    ui->comboBoxDeviceDiscoverName->addItem(openPort );
                    tcpSocket.disconnectFromHost();
                }
        }
    

    If I don't need syncronous approach with threads, could you please give me a suggestion to scan ports ? Thank you in advance.

    Regards

    J 1 Reply Last reply 13 Jun 2023, 10:40
    0
    • T TokaraForest
      13 Jun 2023, 10:29

      Hi,

      I have a TCP Client GUI application that sends read requests periodically once it connects to server side. For now, client and server side runs on my pc and I use my local address. I have followed and edited my application according to Fortune Client Example.There are two push buttons. First one scans available ip addresses and the other one connects to server after I write Port value on a linedit and select ip address on comboBox. Here my code so far:

      widget.h:

      #ifndef WIDGET_H
      #define WIDGET_H
      
      #include <QWidget>
      #include <QAbstractSocket>
      #include <QDebug>
      #include <QHostAddress>
      #include <QMessageBox>
      #include <QString>
      #include <QTcpSocket>
      #include <QHostInfo>
      #include <QNetworkInterface>
      
      
      QT_BEGIN_NAMESPACE
      namespace Ui { class Widget; }
      QT_END_NAMESPACE
      
      class Widget : public QWidget
      {
          Q_OBJECT
      
      public:
          Widget(QWidget *parent = nullptr);
          ~Widget();
      
      private slots:
          void readSocket();
      
          void discardSocket();
      
          void displayError(QAbstractSocket::SocketError socketError);
      
          void on_pushButtonConnect_clicked();
      
          void connected();
      
          void enablePushButtonConnectButton();
      
          void on_pushButtonScan_clicked();
      
      private:
          Ui::Widget *ui;
      
          QTcpSocket *tcpSocket = nullptr;
      };
      #endif // WIDGET_H
      
      

      widget.cpp:

      #include "widget.h"
      #include "ui_widget.h"
      
      Widget::Widget(QWidget *parent)
          : QWidget(parent)
          , ui(new Ui::Widget)
      {
          ui->setupUi(this);
      
          tcpSocket = new QTcpSocket(this);
      
          ui->pushButtonConnect->setDefault(true);
          ui->pushButtonConnect->setEnabled(false);
      
          connect(ui->comboBoxServerName, &QComboBox::editTextChanged,
                  this, &Widget::enablePushButtonConnectButton);
          connect(ui->lineEditServerPort, &QLineEdit::textChanged,
                  this, &Widget::enablePushButtonConnectButton);
          connect(tcpSocket, &QTcpSocket::connected,
                  this, &Widget::connected);
          connect(tcpSocket, &QTcpSocket::readyRead,
                  this, &Widget::readSocket);
          connect(tcpSocket, &QAbstractSocket::errorOccurred,
                  this, &Widget::displayError);
      }
      
      Widget::~Widget()
      {
          delete ui;
      }
      
      void Widget::readSocket()
      {
          QByteArray buffer;
      
          buffer = tcpSocket->readAll();
      
          qDebug() << buffer;
      }
      
      void Widget::displayError(QAbstractSocket::SocketError socketError)
      {
          switch (socketError) {
              case QAbstractSocket::RemoteHostClosedError:
              break;
              case QAbstractSocket::HostNotFoundError:
                  QMessageBox::information(this, "QTCPClient", "The host was not found. Please check the host name and port settings.");
              break;
              case QAbstractSocket::ConnectionRefusedError:
                  QMessageBox::information(this, "QTCPClient", "The connection was refused by the peer. Make sure QTCPServer is running, and check that the host name and port settings are correct.");
              break;
              default:
                  QMessageBox::information(this, "QTCPClient", QString("The following error occurred: %1.").arg(tcpSocket->errorString()));
              break;
          }
      }
      
      void Widget::on_pushButtonConnect_clicked()
      {
          ui->pushButtonConnect->setEnabled(false);
          tcpSocket->abort();
      
          tcpSocket->connectToHost(ui->comboBoxServerName->currentText(),
                                   ui->lineEditServerPort->text().toInt());
      }
      
      void Widget::connected()
      {
          qDebug() << "connected";
      }
      
      void Widget::enablePushButtonConnectButton()
      {
          ui->pushButtonConnect->setEnabled(!ui->comboBoxServerName->currentText().isEmpty() &&
                                       !ui->lineEditServerPort->text().isEmpty());
      }
      
      void Widget::on_pushButtonScan_clicked()
      {
          ui->comboBoxServerName->setEditable(true);
          QString name = QHostInfo::localHostName();
          if (!name.isEmpty()) {
              ui->comboBoxServerName->addItem(name);
              QString domain = QHostInfo::localDomainName();
              if (!domain.isEmpty())
                  ui->comboBoxServerName->addItem(name + QChar('.') + domain);
          }
      
          if (name != QLatin1String("localhost"))
              ui->comboBoxServerName->addItem(QString("localhost"));
          // find out IP addresses of this machine
          QList<QHostAddress> ipAddressesList = QNetworkInterface::allAddresses();
          // add non-localhost addresses
          for (int i = 0; i < ipAddressesList.size(); ++i) {
              if (!ipAddressesList.at(i).isLoopback())
                  ui->comboBoxServerName->addItem(ipAddressesList.at(i).toString());
          }
          // add localhost addresses
          for (int i = 0; i < ipAddressesList.size(); ++i) {
              if (ipAddressesList.at(i).isLoopback())
                  ui->comboBoxServerName->addItem(ipAddressesList.at(i).toString());
          }
      }
      
      

      Now I want to scan ports between 1500-1600 with scan button and see available port values on comboBox. Then I can connect a server with fixed ip address and port value selected on comboBox.
      When I enter wrong port value on linedit, client tries to connect for a while then shows error message. If I try to connect available ports between 1500-1600 in a for loop, it will take time. Also I don't think this is the way.
      There is Blocking Fortune Client example that has synchronous approach. This example uses waitFor....() functions in a non-GUI thread as I understand.
      So do I change my client application's asynchronous approach to syncronous approach ? Would it be the appropriate way with Blocking Fortune example to scan ports by writing something like this ?:

      quint16 start = 1500;
      quint16 end = 1600;
      quint16 timeoutInt = 50;
      
      for(quint16 i = start; i < end; i++){
                  tcpSocket.connectToHost(host, i);
                  if(tcpSocket.waitForConnected(timeoutInt)){
                      qInfo() << "Open Port: " << i;
                      QString openPort = QString::number(i);
                      ui->comboBoxDeviceDiscoverName->addItem(openPort );
                      tcpSocket.disconnectFromHost();
                  }
          }
      

      If I don't need syncronous approach with threads, could you please give me a suggestion to scan ports ? Thank you in advance.

      Regards

      J Offline
      J Offline
      JonB
      wrote on 13 Jun 2023, 10:40 last edited by JonB
      #2

      @TokaraForest
      I don't see that it will make any difference whether you stick with asynchronous approach (which does not block) in UI thread or use synchronous approach with waitFor...() in a thread (which will block that thread but not the Ui thread). Either way scanning 100 ports will take some time because each port has to have time to timeout. It will be "slow". You might as well use asynchronous and not get involved with threads if this is what you have to do.

      But why do you want to scan ports, and at which side? Client should be able to be set to use any available port to connect to server (this is fast). And server needs to specify which port it will be listening on, there is no point it finding a free one as client will not know which one it picked to connect on.

      1 Reply Last reply
      3

      2/2

      13 Jun 2023, 10:40

      • Login

      • Login or register to search.
      2 out of 2
      • First post
        2/2
        Last post
      0
      • Categories
      • Recent
      • Tags
      • Popular
      • Users
      • Groups
      • Search
      • Get Qt Extensions
      • Unsolved