[Qt Development Process] UDP

Overview

UDP (User Datagram Protocol)It is a simple transport layer protocol. Unlike TCP, UDP does not provide reliable data transmission and error detection mechanisms. UDP is mainly used for applications that have high real-time requirements and low data transmission reliability requirements, such as audio, video, real-time games, etc.

UDPUse connectionless datagram transmission mode. Before transmitting data, the sender and receiver do not need to establish a persistent connection, they only need to send data messages. Each data message is independent and has no context, so there is no guarantee that it will be received in the order in which it was sent.

Features of the UDP protocol include:

  1. No connectivity: No connection is required to establish and maintain between the sender and receiver.
  2. Fastness: Due to the lack of connectivity, UDP transfer speed is relatively fast.
  3. No reliability guarantee: UDP does not provide reliable data transmission and does not guarantee the integrity and correctness of data.
  4. Simplicity: The UDP protocol header is shorter and takes up less data transmission.

UDP data transmission diagram:
Insert image description here

QUdpSocket

QUdpSocket类 provides a UDP socket.
QUdpSocket is a subclass of QAbstractSocket that allows sending and receiving UDP datagrams.
Here socket is the so-called socket. Simply put, it is an IP address + a Port number.
The most common way to use this class is to use bind() to bind to an address and port, and then call writeDatagram() and signal, the incoming datagram should be read, otherwise the signal will not be emitted for the next datagram. Note: When receiving the to read it. or returns true. Call pendingDatagramSize() to get the size of the first pending datagram, and call signal is emitted whenever a datagram arrives. In this case, A . signal each time it writes a datagram to the network. If you just want to send datagrams, you don't need to call A socket emits the . to transmit data. If you want to use the standard QIODevice functions read(), readLine(), write(), etc., you must first connect the socket directly to the peer by calling readDatagram() / receiveDatagram()connectToHost()
bytesWritten()bind()
readyRead()hasPendingDatagrams()readDatagram()receiveDatagram()
readyRead()

QUdpSocket supports IPv4 broadcast, which is a way of sending data in an IPv4 network to all hosts on the same network.
In an IPv4 network, the broadcast address is a special IP address used to indicate all hosts in the corresponding network.

IPv4 broadcast uses a specific IP address, that is, when all host bits of the network address are 1, the host address is 0. For example, in a network of 192.168.0.0/24, the broadcast address is 192.168.0.255.

Using IPv4 broadcast, data can be sent to all hosts on the same network at once instead of sending it to each host one by one. This is very useful in some applications, such as notifying all hosts in a LAN to perform a certain operation, or distributing IP addresses in the DHCP protocol, etc.

However, since data sent by IPv4 broadcasts will be received by all hosts on the same network, this may also cause some security and performance issues. Therefore, the use of broadcasts in IPv4 networks requires caution and appropriate restrictions and controls on broadcasts.

For example:

  void Server::initSocket()
  {
    
    
      udpSocket = new QUdpSocket(this);
      udpSocket->bind(QHostAddress::LocalHost, 7755);

      connect(udpSocket, SIGNAL(readyRead()),
              this, SLOT(readPendingDatagrams()));
  }

  void Server::readPendingDatagrams()
  {
    
    
      while (udpSocket->hasPendingDatagrams()) {
    
    
          QNetworkDatagram datagram = udpSocket->receiveDatagram();
          processTheDatagram(datagram);
      }
  }

QUdpSocket also supports UDP multicast. Use joinMulticastGroup() and leaveMulticastGroup() to control group membership, and QAbstractSocket::MulticastTtlOption and QAbstractSocket::MulticastLoopbackOption to set , you can also use connectToHost() to establish a virtual connection with the UDP server, and then use read() and write() to exchange datagrams without specifying each the receiver of the datagram. Using to query. to control the outbound interface of multicast datagrams, and use socket options. Use TTL and loopbacksetMulticastInterface()multicastInterface()
QUdpSocket

Example

The following is a sender and a receiver. The sender sends data regularly and the receiver displays it.
sender.h

#include <QWidget>

QT_BEGIN_NAMESPACE
class QDialogButtonBox;
class QLabel;
class QPushButton;
class QTimer;
class QUdpSocket;
QT_END_NAMESPACE

class Sender : public QWidget
{
    
    
    Q_OBJECT

public:
    Sender(QWidget *parent = 0);

private slots:
    void startBroadcasting();
    void broadcastDatagram();

private:
    QLabel *statusLabel;
    QPushButton *startButton;
    QPushButton *quitButton;
    QDialogButtonBox *buttonBox;
    QUdpSocket *udpSocket;
    QTimer *timer;
    int messageNo;
};

sender.cpp

#include <QtWidgets>
#include <QtNetwork>

#include "sender.h"

Sender::Sender(QWidget *parent)
    : QWidget(parent)
{
    
    
    statusLabel = new QLabel(tr("绑定 端口 45454"));
    statusLabel->setWordWrap(true);

    startButton = new QPushButton(tr("&Start"));
    quitButton = new QPushButton(tr("&Quit"));

    buttonBox = new QDialogButtonBox;
    buttonBox->addButton(startButton, QDialogButtonBox::ActionRole);
    buttonBox->addButton(quitButton, QDialogButtonBox::RejectRole);

    timer = new QTimer(this);

    udpSocket = new QUdpSocket(this);

    messageNo = 1;

    connect(startButton, SIGNAL(clicked()), this, SLOT(startBroadcasting()));
    connect(quitButton, SIGNAL(clicked()), this, SLOT(close()));
    connect(timer, SIGNAL(timeout()), this, SLOT(broadcastDatagram()));

    QVBoxLayout *mainLayout = new QVBoxLayout;
    mainLayout->addWidget(statusLabel);
    mainLayout->addWidget(buttonBox);
    setLayout(mainLayout);

    setWindowTitle(tr("广播发送"));
}

void Sender::startBroadcasting()
{
    
    
    startButton->setEnabled(false);
    timer->start(1000);
}

void Sender::broadcastDatagram()
{
    
    
    statusLabel->setText(tr("现在 广播 信息 %1").arg(messageNo));

    QByteArray datagram = "广播 信息 " + QByteArray::number(messageNo);
    udpSocket->writeDatagram(datagram.data(), datagram.size(),
                             QHostAddress::Broadcast, 45454);

    ++messageNo;
}

receiver.h

#include <QWidget>

QT_BEGIN_NAMESPACE
class QLabel;
class QPushButton;
class QUdpSocket;
class QAction;
QT_END_NAMESPACE

class Receiver : public QWidget
{
    
    
    Q_OBJECT

public:
    Receiver(QWidget *parent = 0);

private slots:
    void processPendingDatagrams();

private:
    QLabel *statusLabel;
    QPushButton *quitButton;
    QUdpSocket *udpSocket;
};

receiver.cpp

#include <QtWidgets>
#include <QtNetwork>

#include "receiver.h"

Receiver::Receiver(QWidget *parent)
    : QWidget(parent)
{
    
    
    statusLabel = new QLabel(tr("监听 广播 信息"));
    statusLabel->setWordWrap(true);

    quitButton = new QPushButton(tr("&Quit"));

    udpSocket = new QUdpSocket(this);
    udpSocket->bind(45454, QUdpSocket::ShareAddress);

    connect(udpSocket, SIGNAL(readyRead()),
            this, SLOT(processPendingDatagrams()));

    connect(quitButton, SIGNAL(clicked()), this, SLOT(close()));

    QHBoxLayout *buttonLayout = new QHBoxLayout;
    buttonLayout->addStretch(1);
    buttonLayout->addWidget(quitButton);
    buttonLayout->addStretch(1);

    QVBoxLayout *mainLayout = new QVBoxLayout;
    mainLayout->addWidget(statusLabel);
    mainLayout->addLayout(buttonLayout);
    setLayout(mainLayout);

    setWindowTitle(tr("广播 接收"));
}

void Receiver::processPendingDatagrams()
{
    
    
    while (udpSocket->hasPendingDatagrams()) {
    
    
        QByteArray datagram;
        datagram.resize(udpSocket->pendingDatagramSize());
        udpSocket->readDatagram(datagram.data(), datagram.size());
        statusLabel->setText(tr("接收 数据: \"%1\"")
                             .arg(datagram.data()));
    }
}

Effect

The default display is as follows:
Insert image description here
When clicking Send:
Insert image description here

in conclusion

青春就像一只容器,装满了不安躁动青涩与偶尔的疯狂

Guess you like

Origin blog.csdn.net/MrHHHHHH/article/details/135038984