Qt UDP 通信类详解与实现

这是一个基于 Qt 框架的 UDP 通信类实现,用于处理 UDP 数据包的发送和接收。下面是对这个代码的详细介绍:

功能概述

这个 UDPCommunication 类提供了以下核心功能:

  • 发送 UDP 数据包到指定地址和端口
  • 监听指定端口接收 UDP 数据
  • 发送特定格式的监控数据(01 0A 55)
  • 处理通信错误和异常情况

类结构详解

公共方法

  1. 构造函数/析构函数:初始化/清理 UDP socket
  2. sendUdpData():发送原始数据到指定地址和端口
  3. startListening():在指定端口开始监听
  4. stopListening():停止监听
  5. sendMonitoringData():发送预设的监控数据(01 0A 55)

信号

  1. dataReceived():当接收到数据时发出,包含数据内容和发送方信息
  2. errorOccurred():发生错误时发出,包含错误信息

私有槽函数

  • onReadyRead():处理接收到的数据

成员变量

  • udpSocket:QUdpSocket 实例,用于实际的 UDP 通信
  • listeningPort:当前监听的端口号

核心功能实现

数据发送

cpp 复制代码
bool sendUdpData(const QHostAddress &address, quint16 port, const QByteArray &data);

使用 writeDatagram() 方法发送数据,并检查发送结果。

数据接收

通过连接 QUdpSocket::readyRead 信号到 onReadyRead() 槽函数,在有数据到达时自动处理。

端口监听

cpp 复制代码
bool startListening(quint16 port);

使用 bind() 方法绑定到指定端口开始监听。

错误处理

通过连接 errorOccurred 信号来捕获和处理 socket 错误。

使用示例

cpp 复制代码
// 创建实例
UDPCommunication udp;

// 开始监听端口 4000
udp.startListening(4000);

// 发送数据到目标设备
QByteArray data = "Hello UDP";
udp.sendUdpData(QHostAddress("192.168.1.100"), 4010, data);

// 发送预设的监控数据
udp.sendMonitoringData(QHostAddress("192.168.1.100"), 4010);

// 连接信号处理接收到的数据
connect(&udp, &UDPCommunication::dataReceived, [](const QByteArray &data, const QHostAddress &sender, quint16 port) {
    qDebug() << "Received from" << sender.toString() << ":" << data;
});

特点

  1. 封装良好:将复杂的 UDP socket 操作封装成简单易用的接口
  2. 错误处理完善:提供详细的错误信息和异常处理
  3. 线程安全:基于 Qt 的信号槽机制,适合多线程环境
  4. 灵活性强:支持任意数据的发送和接收
  5. 调试友好:包含详细的调试输出

适用场景

  • 网络设备监控和控制
  • 实时数据采集系统
  • 分布式系统间的轻量级通信
  • 需要简单可靠 UDP 通信的各种应用

这个类提供了一个完整且健壮的 UDP 通信解决方案,可以直接集成到 Qt 项目中使用。

完整代码

UDPCommunication.h

cpp 复制代码
#ifndef UDPCOMMUNICATION_H
#define UDPCOMMUNICATION_H

#include <QObject>
#include <QUdpSocket>
#include <QByteArray>
#include <QHostAddress>

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

    // 发送 UDP 数据包
    bool sendUdpData(const QHostAddress &address, quint16 port, const QByteArray &data);

    // 开始监听指定端口接收数据
    bool startListening(quint16 port);

    // 停止监听
    void stopListening();

    // 便捷方法:发送特定格式的数据到指定地址和端口
    bool sendMonitoringData(const QHostAddress &address = QHostAddress("192.168.0.119"),
                            quint16 port = 4010);

signals:
    // 当接收到数据时发出信号
    void dataReceived(const QByteArray &data, const QHostAddress &sender, quint16 port);

    // 当发生错误时发出信号
    void errorOccurred(const QString &errorString);

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

private:
    QUdpSocket *udpSocket;
    quint16 listeningPort;
};


#endif // UDPCOMMUNICATION_H

UDPCommunication.cpp

cpp 复制代码
#include "UDPCommunication.h"
#include <QDebug>

UDPCommunication::UDPCommunication(QObject *parent)
    : QObject(parent), udpSocket(nullptr), listeningPort(0)
{
    udpSocket = new QUdpSocket(this);
    connect(udpSocket, &QUdpSocket::readyRead, this, &UDPCommunication::onReadyRead);
    connect(udpSocket, QOverload<QUdpSocket::SocketError>::of(&QUdpSocket::errorOccurred),
            [this](QUdpSocket::SocketError error) {
                emit errorOccurred(udpSocket->errorString());
            });
}

UDPCommunication::~UDPCommunication()
{
    stopListening();
}

bool UDPCommunication::sendUdpData(const QHostAddress &address, quint16 port, const QByteArray &data)
{
    if (!udpSocket) {
        emit errorOccurred("UDP socket is not initialized");
        return false;
    }

    qint64 bytesSent = udpSocket->writeDatagram(data, address, port);
    if (bytesSent == -1) {
        emit errorOccurred(udpSocket->errorString());
        return false;
    }

    qDebug() << "Sent" << bytesSent << "bytes to" << address.toString() << ":" << port;
    return true;
}

bool UDPCommunication::startListening(quint16 port)
{
    if (!udpSocket) {
        emit errorOccurred("UDP socket is not initialized");
        return false;
    }

    if (udpSocket->state() == QAbstractSocket::BoundState) {
        udpSocket->close();
    }

    if (udpSocket->bind(port)) {
        listeningPort = port;
        qDebug() << "Started listening on port" << port;
        return true;
    } else {
        emit errorOccurred(udpSocket->errorString());
        return false;
    }
}

void UDPCommunication::stopListening()
{
    if (udpSocket && udpSocket->state() == QAbstractSocket::BoundState) {
        udpSocket->close();
        listeningPort = 0;
        qDebug() << "Stopped listening";
    }
}

bool UDPCommunication::sendMonitoringData(const QHostAddress &address, quint16 port)
{
    // 创建要发送的数据:01 0A 55
    QByteArray data;
    data.append(0x01);
    data.append(0x0A);
    data.append(0x55);

    return sendUdpData(address, port, data);
}

void UDPCommunication::onReadyRead()
{
    if (!udpSocket) return;

    while (udpSocket->hasPendingDatagrams()) {
        QByteArray datagram;
        datagram.resize(udpSocket->pendingDatagramSize());
        QHostAddress sender;
        quint16 senderPort;

        qint64 bytesRead = udpSocket->readDatagram(datagram.data(), datagram.size(), &sender, &senderPort);
        if (bytesRead == -1) {
            emit errorOccurred(udpSocket->errorString());
            continue;
        }

        qDebug() << "Received" << bytesRead << "bytes from" << sender.toString() << ":" << senderPort;
        emit dataReceived(datagram, sender, senderPort);
    }
}
相关推荐
REDcker41 分钟前
浏览器端Web程序性能分析与优化实战 DevTools指标与工程清单
开发语言·前端·javascript·vue·ecmascript·php·js
ACP广源盛139246256731 小时前
IX8024与科学大模型的碰撞@ACP#筑牢科研 AI 算力高速枢纽分享
运维·服务器·网络·数据库·人工智能·嵌入式硬件·电脑
Empty-Filled2 小时前
AI生成测试用例功能怎么测:一个完整实战案例
网络·人工智能·测试用例
我命由我123452 小时前
Kotlin 开发 - lateinit 关键字
android·java·开发语言·kotlin·android studio·android-studio·android runtime
智者知已应修善业2 小时前
【51单片机2个按键控制流水灯运行与暂停】2023-9-6
c++·经验分享·笔记·算法·51单片机
Halo_tjn2 小时前
Java Set集合相关知识点
java·开发语言·算法
码云数智-大飞2 小时前
本地部署大模型:隐私安全与多元优势一站式解读
运维·网络·人工智能
许彰午3 小时前
我手写了一个 Java 内存数据库(二):B+ 树的插入与分裂
java·开发语言·面试
jinanwuhuaguo3 小时前
(第二十九篇)OpenClaw 实时与具身的跃迁——从异步孤岛到数字世界的“原住民”
前端·网络·人工智能·重构·openclaw
大飞记Python3 小时前
【2026更新】Python基础学习指南(AI版)——04数据类型
开发语言·人工智能·python