[QT] make a network debugging assistant by hand (UDP design)

Use of TCP and UDP network communication classes

Pornhub

1. Procedure framework construction

Then, in the last article, we began to design the related functions of UDP. First, hide the related UDP configuration;

1.1 explanation of constructor

MainWindow::MainWindow(QWidget *parent):QMainWindow(parent),ui(new Ui::MainWindow)

Its meaning is to execute the constructor of the parent QWidget and create a UI class object UI of Ui::MainWindow. This UI is the pointer variable UI defined in the private part of the Widget.

UI - > setupui (this) is executed in the constructor; It is equivalent to executing the setupUi() function of Ui::Widget class. This function can realize the generation of window, the setting of various attributes, and the association between signal and slot.

The destructor deletes the pointer ui created by new.  

1.2 shielding UDP components

We hope that UDP components will not be displayed in the initial state of the interface.

    ui->txtUdpTxIP->hide();
    ui->spbUdpTxPort->hide();
    ui->cbbTxPort->hide();

1.3 declaring UDP objects

Declare an object of UDP class in private in the header file;

QUdpSocket *udp;

Then make a statement in. cpp;

udp = new QUdpSocket(this);

2. Preparations for UI initialization

2.1 list supported network communication types

Header file public: initialization: void listNetworkType(QComboBox *cbbNetworkType);

/**
 * @brief MainWindow::listNetworkType Lists the supported network communication types
 * @param cbbNetworkType
 */
void MainWindow::listNetworkType(QComboBox *cbbNetworkType)
{
    QMetaEnum mtaEnum = QMetaEnum::fromType<MainWindow::NetworkType>();
    for (int i = 0; i < mtaEnum.keyCount(); i++) {
        cbbNetworkType->addItem(mtaEnum.key(i), mtaEnum.value(i));
    }
    cbbNetworkType->setCurrentText("UDP"); // Set defaults
}

2.2 get the host's IPV4

Header file public: initialization: QStringList getHostAddress();

/**
 * @brief MainWindow::getHostAddress Gets the IPv4 of the host
 */
QStringList MainWindow::getHostAddress()
{
    QList<QHostAddress> addrList = QNetworkInterface::allAddresses();
    QStringList tmp;
    foreach (QHostAddress hostAddr, addrList){
        if(hostAddr.protocol() == QAbstractSocket::IPv4Protocol){
            if(hostAddr.toString().contains("127.0.")) continue;
            tmp<<hostAddr.toString();
        }
        else if (hostAddr.isNull())  // Host address is empty
            continue;
    }
    return tmp;
}

2.3 interface modification under UDP and TCP modes

Header file public: initialization: void initComboBoxUDP();

void MainWindow::initComboBoxUDP()
{
    ui->lblIP->setText("local IP");
    ui->btnLink->setText("connect");
    ui->cbbTxPort->hide();
    ui->txtUdpTxIP->show();
    ui->spbUdpTxPort->show();
}

Interface modification in TCPServer mode  

void initComboBoxServer();

void initComboBoxClient();

/**
 * @brief MainWindow::initComboBoxServer Interface modification server
 */
void MainWindow::initComboBoxServer()
{
    ui->lblIP->setText("local IP");
    ui->btnLink->setText("monitor");
    ui->txtUdpTxIP->hide();
    ui->spbUdpTxPort->hide();
    ui->cbbTxPort->show();
}
/**
 * @brief MainWindow::initComboBoxClient Interface modification client
 */
void MainWindow::initComboBoxClient()
{
    ui->lblIP->setText("long-range IP");
    ui->btnLink->setText("connect");
    ui->txtUdpTxIP->hide();
    ui->spbUdpTxPort->hide();
    ui->cbbTxPort->show();
}

2.4 UDP initialization drop-down list

Header file public: void initComboBox_Config();

/**
 * @brief MainWindow::initComboBox_Config Initialize drop-down list
 *
 */
void MainWindow::initComboBox_Config()
{
    this->listNetworkType( ui->cbbNetType );
    QStringList hostAddrList = getHostAddress();
    if( !hostAddrList.isEmpty() )
        ui->txtIP->setText( hostAddrList.at(0) );
    this->initComboBoxUDP();
}

2.5 switch three communication modes from the drop-down list

/**
 * @brief MainWindow::on_cbbNetType_currentIndexChanged Switching communication mode
 * @param index
 */
void MainWindow::on_cbbNetType_currentIndexChanged(int index)
{
    switch(index){
    case TCPServer:
        this->initComboBoxServer();
        break;
    case TCPClient:
        this->initComboBoxClient();
        break;
    case UDP:
        this->initComboBoxUDP();
        break;
    }
}

2.6 connection button events

Get the value of the drop-down list:

    enum NetworkType{
        TCPServer  = 0,
        TCPClient  = 1,
        UDP        = 2,
    };
    Q_ENUM(NetworkType)
    NetworkType networkType = (NetworkType)ui->cbbNetType->currentIndex();

List the types of enumeration, and read the current value according to the drop-down list;

Then judge if the connection button has been clicked; Judge the value of the drop-down list. If it is TCPServer, listen. If it is tcpcclient, connect to the remote server. If it is UDP, bind the port number;

If no connection is clicked, disconnect the above interface;

Declare a pointer in the header file;

   QTcpServer *server;
    QTcpSocket *client;
    QList<QTcpSocket *>clients;
void MainWindow::on_btnLink_clicked(bool checked)
{
    NetworkType networkType = (NetworkType)ui->cbbNetType->currentIndex();

    bool ok = false;
    if(checked){
        switch(networkType){
        case TCPServer:
      //      ok = this->startListen();
            break;
        case TCPClient:
     //       ok = this->connectRemoteServer();
            break;
        case UDP:
     //       ok = this->bindAddrAndPort();
            break;
        }
        ok? ui->cbbNetType->setEnabled(false): ui->cbbNetType->setEnabled(true);
    }else{
        switch(networkType){
        case TCPServer:
      //      this->stopListen();
            break;
        case TCPClient:
     //       this->disconnectRemoteServer();
            break;
        case UDP:
      //      this->unbindAddrAndPort();
            break;
        default:break;
        }
        ui->cbbNetType->setEnabled(true);
    }
}

Now, according to the above process, improve the correlation function;

2.7 UDP communication

Each time UDP sends a datagram, it must specify the destination address and port number;

QUdpSocket *udp; Declare the UDP class in the header file to realize UDP communication;

UDP data reception requires

The QUdpSocket::bid() function binds a port; Used to receive incoming datagrams,

udp->bind( *ip, port );

Obtain client IP; Obtain the port number;

Listening function, return bool value;

2.7.1 add status bar

Right click and select Add status bar;

In the name of the promotion class, name it statusBar

ui->statusBar->showMessage("Listening");

  2.7.2 defining slot functions

public slots:
    void slots_udpRxCallback();

2.7.3 insert timestamp

/**
 * @brief MainWindow::insertTimeStamp Insert timestamp prefix
 * @param tmp
 */
void MainWindow::insertTimeStamp(QString &tmp)
{
    QTime currentTime = QTime::currentTime();
    tmp.prepend( "[" + currentTime.toString("hh:mm:ss:zzz") + "]");
}

2.7.4   The data is recorded in the RxBrowser

/**
 * @brief MainWindow::logInRxBrowser The data is recorded in the RxBrowser
 * @param ipInfo ip,port
 * @param tmp
 */
void MainWindow::logInRxBrowser(QString ipInfo, QByteArray &tmp)
{
    if(ui->ckbTimeStamp->isChecked())
        this->insertTimeStamp(ipInfo);

    QString msg;
    if( ui->ckbHexRx->isChecked() ){
        msg = tmp.toHex(' ').toUpper();
    }else{
        msg = QString::fromLocal8Bit(tmp);
    }
    ui->txtRxBrowser->append( ipInfo + msg );
}

Judgment; Timestamp addition;

Judgment; Convert to hexadecimal;

The txtRxBrowser text box outputs ip information and data information

2.7.5 send message and insert server message

/**
 * @brief MainWindow::insertServerInfo Insert server information
 * @param tmp
 */
void MainWindow::insertTxInfo(QString &tmp)
{
    QString ip ;
    QString port;
    NetworkType networkType = (NetworkType)ui->cbbNetType->currentIndex();
    switch(networkType){
  case TCPServer :
        ip       = server->serverAddress().toString();
        port     = QString::number( server->serverPort() );
        break;
    case TCPClient:
        ip       = client->localAddress().toString();
        port     = QString::number( client->localPort() );
        break;
    case UDP:
        ip       = ui->txtIP->text();
        port     = ui->txtPort->text();
        break;
    }
    tmp.prepend( "[" + QString("Tx from %1:%2").arg(ip, port) +"]\n" );
}

2.7.6 receive and insert the IP and port number of the sending end

/**
 * @brief MainWindow::insertRxInfo Insert the IP and port number of the sender
 * @param client
 * @param tmp
 */
void MainWindow::insertRxInfo(QNetworkDatagram *datagram, QString &tmp)
{
    QString ip = datagram->senderAddress().toString();
    QString port = QString::number( datagram->senderPort() );
    tmp.prepend( "[" + QString("Rx from %1:%2").arg(ip, port) +"]\n" );
}

Tags: network Qt udp

Posted on Thu, 04 Nov 2021 15:19:48 -0400 by oh_maestro