UDP socket communication of UDP in QT

Table of contents

UDP:

Example:

Service-Terminal:

client:

Example usage:

Examples of errors and corrections:


UDP:

(User Datagram Protocol is the User Datagram Protocol) is a lightweight, unreliable, datagram-oriented connectionless
protocol. In an environment where the network quality is very unsatisfactory, UDP protocol data packets are seriously lost. Due to the characteristics of UDP: it is not a connection
protocol, so it has the advantages of low resource consumption and fast processing speed, so usually audio, video and ordinary data use UDP more when transmitting,
because even if they occasionally lose one or two data package, it will not have much impact on the receiving result. So QQ, a
chat program that does not require too much confidentiality, uses the UDP protocol.
The QUdpSocket class is provided in Qt to send and receive UDP datagrams (datagrams). Socket simply means
an IP address plus a port.
Process: ①Create a QUdpSocket socket object ②If you need to receive data, you must bind the port ③Use
writeDatagram to send data, and use readDatagram to receive data.

Example:

  1. Import the necessary header files:

#include <QUdpSocket>

  1. Create a UDP socket:

QUdpSocket *udpSocket = new QUdpSocket(this);

  1. Bind local port (optional): Usually, UDP sockets do not need to be bound to a specific local port, but writeDatagram()directly specify the target IP address and port through the function. But if you need to receive data from a specific local port, you can bind:

udpSocket->bind(localPort, QUdpSocket::ShareAddress);

  1. Send data: Use writeDatagram()the function to send data packets to the destination address and port:

QHostAddress targetAddress("192.168.0.100"); // 目标IP地址 quint16 targetPort = 1234; // 目标端口 QByteArray data = "Hello, UDP!"; // 要发送的数据 udpSocket->writeDatagram(data, targetAddress, targetPort);

  1. Receiving data: In order to receive data, we need to connect readyReadthe signal to a slot function and read the data in the slot function:

connect(udpSocket, &QUdpSocket::readyRead, this, &MyClass::readPendingDatagrams);

Then readPendingDatagrams()process the received data in the slot function:

void MyClass::readPendingDatagrams() { while (udpSocket->hasPendingDatagrams()) { QByteArray datagram; datagram.resize(udpSocket->pendingDatagramSize()); udpSocket->readDatagram(datagram.data(), datagram.size()); // 在这里处理接收到的数据 // ... } }

This way, you can use UDP sockets for simple UDP communication in Qt.

Example Explanation: Suppose we have two Qt applications, one as UDP server and the other as UDP client. The server listens on a specific port to receive messages from the client and sends the message back to the client as-is.

Service-Terminal:

#include <QTcpServer>
#include <QTcpSocket>

class Server : public QObject
{
    Q_OBJECT

public:
    Server(QObject *parent = nullptr) : QObject(parent)
    {
        udpSocket = new QUdpSocket(this);
        udpSocket->bind(QHostAddress::Any, 1234);

        connect(udpSocket, &QUdpSocket::readyRead, this, &Server::readPendingDatagrams);
    }

private slots:
    void readPendingDatagrams()
    {
        while (udpSocket->hasPendingDatagrams()) {
            QByteArray datagram;
            datagram.resize(udpSocket->pendingDatagramSize());
            udpSocket->readDatagram(datagram.data(), datagram.size());

            // 将接收到的数据原样发送回客户端
            udpSocket->writeDatagram(datagram, QHostAddress::LocalHost, 5678);
        }
    }

private:
    QUdpSocket *udpSocket;
};

client:

#include <QTcpSocket>

class Client : public QObject
{
    Q_OBJECT

public:
    Client(QObject *parent = nullptr) : QObject(parent)
    {
        udpSocket = new QUdpSocket(this);
    }

    void sendMessage(const QByteArray &message)
    {
        udpSocket->writeDatagram(message, QHostAddress::LocalHost, 1234);
    }

private:
    QUdpSocket *udpSocket;
};

Example usage:

// 在服务器端创建服务器对象
Server server;

// 在客户端创建客户端对象
Client client;

// 客户端发送消息给服务器
client.sendMessage("Hello, server!");

// 服务器会将消息原样发送回客户端

// 可以在客户端的槽函数中处理接收到的消息

The above example demonstrates a simple UDP communication process. In practical applications, you can perform more complex data processing and error handling as required.

Examples of errors and corrections:

In UDP communication, some common examples of errors may include:

Mistake 1: Unbound local port When in use QUdpSocket, if you forget to bind the UDP socket to the local port, data may not be sent or received correctly.

Error example:

QUdpSocket *udpSocket = new QUdpSocket(this); udpSocket->writeDatagram("Hello, UDP!", QHostAddress::LocalHost, 1234);

Correction method: Make sure to bind the UDP socket to the local port before sending or receiving data.

QUdpSocket *udpSocket = new QUdpSocket(this); udpSocket->bind(QHostAddress::Any, 5678); // 绑定本地端口 udpSocket->writeDatagram("Hello, UDP!", QHostAddress::LocalHost, 1234);

Mistake 2: Not processing all datagrams when receiving data In UDP communication, multiple datagrams may arrive at the same time, and if only one of the datagrams is processed, other datagrams may be discarded.

Error example:

void MyClass::readPendingDatagrams() { QByteArray datagram; datagram.resize(udpSocket->pendingDatagramSize()); udpSocket->readDatagram(datagram.data(), datagram.size()); // 处理接收到的数据(仅处理一个数据报) // ... }

Correction: Use a loop to process all pending datagrams.

void MyClass::readPendingDatagrams() { while (udpSocket->hasPendingDatagrams()) { QByteArray datagram; datagram.resize(udpSocket->pendingDatagramSize()); udpSocket->readDatagram(datagram.data(), datagram.size()); // 处理接收到的数据(处理所有数据报) // ... } }

Mistake 3: The data size is not handled correctly when receiving data When the received data size exceeds the pendingDatagramSize()returned value, it may cause data truncation.

Error example:

void MyClass::readPendingDatagrams() { while (udpSocket->hasPendingDatagrams()) { QByteArray datagram; // 问题:未正确处理数据大小,导致截断 datagram.resize(udpSocket->pendingDatagramSize()); udpSocket->readDatagram(datagram.data(), datagram.size()); // 处理接收到的数据 // ... } }

Correction method: Before reading the data, first obtain the actual received data size, and adjust the array size according to the size.

void MyClass::readPendingDatagrams() { while (udpSocket->hasPendingDatagrams()) { QByteArray datagram; datagram.resize(udpSocket->pendingDatagramSize()); // 获取实际接收到的数据大小,并根据该大小调整数组大小 qint64 bytesRead = udpSocket->readDatagram(datagram.data(), datagram.size()); // 处理接收到的数据 // 注意:如果需要使用`bytesRead`来截取datagram的有效部分,确保不使用未读取部分。 // ... } }

These are some common examples of errors and corresponding correction methods. By paying attention to these details, you can better write stable and reliable UDP communication code.

Guess you like

Origin blog.csdn.net/clayhell/article/details/132024020