【QT5 网络编程示例】UDP 通信

文章目录

    • [UDP 通信](#UDP 通信)

UDP 通信

Qt 主要通过 QUdpSocket 类实现 UDP 通信。

常用方法

  • bind(QHostAddress, quint16 port):绑定指定 IP 和端口。
  • writeDatagram(QByteArray, QHostAddress, quint16 port):向指定地址和端口发送数据包。
  • readDatagram(QByteArray &buffer, QHostAddress *sender, quint16 *senderPort):读取接收到的数据包。
  • hasPendingDatagrams():检查是否有待处理的数据包。
  • pendingDatagramSize():获取下一个数据包的大小。

常用信号

  • readyRead():当有数据可读时触发。

下面给出一个简单示例:

https://github.com/BinaryAI-1024/QtStudy/tree/master/network/UDP

服务器端

cpp 复制代码
// udpserver.h
#ifndef UDPSERVER_H
#define UDPSERVER_H

#include <QUdpSocket>
#include <QObject>

class UdpServer : public QObject {
    Q_OBJECT
public:
    explicit UdpServer(QObject *parent = nullptr);
    ~UdpServer();

    void startServer(quint16 port); // 启动服务器

private slots:
    void onReadyRead(); // 处理接收的数据

private:
    QUdpSocket *udpSocket; // UDP 套接字
};

#endif // UDPSERVER_H
cpp 复制代码
// udpserver.cpp
#include "udpserver.h"
#include <QDebug>

// 构造函数,初始化 QUdpSocket 并连接 readyRead 信号
UdpServer::UdpServer(QObject *parent) : QObject(parent), udpSocket(new QUdpSocket(this)) {
    // 当有数据可读时,触发 onReadyRead 处理数据
    connect(udpSocket, &QUdpSocket::readyRead, this, &UdpServer::onReadyRead);
}

// 析构函数,关闭 UDP 套接字
UdpServer::~UdpServer() {
    udpSocket->close();
}

// 绑定端口
void UdpServer::startServer(quint16 port) {
    if (udpSocket->bind(QHostAddress::Any, port)) { // 绑定到所有可用的网络接口
        qDebug() << "UDP Server started on port" << port;
    } else {
        qDebug() << "UDP Server failed to start!";
    }
}

// 处理接收到的数据
void UdpServer::onReadyRead() {
    while (udpSocket->hasPendingDatagrams()) { // 检查是否有未处理的数据包
        QByteArray datagram;
        datagram.resize(udpSocket->pendingDatagramSize()); // 调整数组大小以容纳数据
        QHostAddress sender; // 发送方 IP 地址
        quint16 senderPort;  // 发送方端口号

        // 读取数据包,并获取发送方地址和端口
        udpSocket->readDatagram(datagram.data(), datagram.size(), &sender, &senderPort);
        qDebug() << "Received from" << sender.toString() << ":" << senderPort << "->" << datagram;

        // 发送响应数据回给客户端
        udpSocket->writeDatagram("Hello from server!", sender, senderPort);
    }
}

客户端

cpp 复制代码
// udpclient.h
#ifndef UDPCLIENT_H
#define UDPCLIENT_H

#include <QUdpSocket>
#include <QObject>

class UdpClient : public QObject {
    Q_OBJECT
public:
    explicit UdpClient(QObject *parent = nullptr);
    ~UdpClient();

    void sendMessage(const QString &message, const QString &host, quint16 port);

private slots:
    void onReadyRead(); // 处理服务器返回的数据

private:
    QUdpSocket *udpSocket;
};

#endif // UDPCLIENT_H
cpp 复制代码
// udpclient.cpp
#include "udpclient.h"
#include <QDebug>

// 构造函数,初始化 QUdpSocket 并连接 readyRead 信号
UdpClient::UdpClient(QObject *parent) : QObject(parent), udpSocket(new QUdpSocket(this)) {
    // 当有数据可读时,触发 onReadyRead 处理数据
    connect(udpSocket, &QUdpSocket::readyRead, this, &UdpClient::onReadyRead);
}

// 析构函数,关闭 UDP 套接字
UdpClient::~UdpClient() {
    udpSocket->close();
}

// 发送 UDP 数据到指定的 IP 和端口
void UdpClient::sendMessage(const QString &message, const QString &host, quint16 port) {
    udpSocket->writeDatagram(message.toUtf8(), QHostAddress(host), port);
}

// 处理接收到的数据
void UdpClient::onReadyRead() {
    while (udpSocket->hasPendingDatagrams()) { // 检查是否有未处理的数据包
        QByteArray datagram;
        datagram.resize(udpSocket->pendingDatagramSize()); // 调整数组大小以容纳数据
        udpSocket->readDatagram(datagram.data(), datagram.size()); // 读取数据包
        qDebug() << "Received from server:" << datagram; // 输出接收到的数据
    }
}

主函数

cpp 复制代码
// main.cpp
#include <QCoreApplication>
#include "udpserver.h"
#include "udpclient.h"

int main(int argc, char *argv[]) {
    QCoreApplication a(argc, argv);

    // 启动服务器
    UdpServer server;
    server.startServer(12345);

    // 启动客户端并发送消息
    UdpClient client;
    client.sendMessage("Hello from client!", "127.0.0.1", 12345);

    return a.exec();
}

运行结果:

plaintext 复制代码
UDP Server started on port 12345
Received from "::ffff:127.0.0.1" : 59792 -> "Hello from client!"
Received from server: "Hello from server!"

UDP 服务器和客户端都可以相互发送数据,不需要建立连接。

相关推荐
十年编程老舅11 分钟前
‌C++左值与右值:从基础概念到核心应用‌
linux·c++·右值引用·c++17·c++左值·c++右值·左值引用
John_ToDebug23 分钟前
Chrome性能黑魔法:深入浅出PGO优化与实战指南
c++·chrome
和光同尘 、Y_____42 分钟前
BRepMesh_IncrementalMesh 重构生效问题
c++·算法·图形渲染
起个名字费劲死了2 小时前
手眼标定之已知同名点对,求解转换RT,备份记录
c++·数码相机·机器人·几何学·手眼标定
雅雅姐2 小时前
C++中的单例模式的实现
c++
lingran__2 小时前
速通ACM省铜第一天 赋源码(The Cunning Seller (hard version))
c++·算法
沐怡旸2 小时前
【基础知识】仿函数与匿名函数对比
c++·面试
LoveXming4 小时前
Chapter4—工厂方法模式
c++·设计模式·简单工厂模式·工厂方法模式·开闭原则
青草地溪水旁4 小时前
设计模式(C++)详解—工厂方法模式(2)
c++·工厂方法模式
深耕AI4 小时前
MFC 图形设备接口详解:小白从入门到掌握
c++·mfc