这是一个基于 Qt 框架的 UDP 通信类实现,用于处理 UDP 数据包的发送和接收。下面是对这个代码的详细介绍:
功能概述
这个 UDPCommunication
类提供了以下核心功能:
- 发送 UDP 数据包到指定地址和端口
- 监听指定端口接收 UDP 数据
- 发送特定格式的监控数据(01 0A 55)
- 处理通信错误和异常情况
类结构详解
公共方法
- 构造函数/析构函数:初始化/清理 UDP socket
- sendUdpData():发送原始数据到指定地址和端口
- startListening():在指定端口开始监听
- stopListening():停止监听
- sendMonitoringData():发送预设的监控数据(01 0A 55)
信号
- dataReceived():当接收到数据时发出,包含数据内容和发送方信息
- errorOccurred():发生错误时发出,包含错误信息
私有槽函数
- onReadyRead():处理接收到的数据
成员变量
udpSocket
:QUdpSocket 实例,用于实际的 UDP 通信listeningPort
:当前监听的端口号
核心功能实现
数据发送
bool sendUdpData(const QHostAddress &address, quint16 port, const QByteArray &data);
使用 writeDatagram()
方法发送数据,并检查发送结果。
数据接收
通过连接 QUdpSocket::readyRead
信号到 onReadyRead()
槽函数,在有数据到达时自动处理。
端口监听
bool startListening(quint16 port);
使用 bind()
方法绑定到指定端口开始监听。
错误处理
通过连接 errorOccurred
信号来捕获和处理 socket 错误。
使用示例
// 创建实例
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;
});
特点
- 封装良好:将复杂的 UDP socket 操作封装成简单易用的接口
- 错误处理完善:提供详细的错误信息和异常处理
- 线程安全:基于 Qt 的信号槽机制,适合多线程环境
- 灵活性强:支持任意数据的发送和接收
- 调试友好:包含详细的调试输出
适用场景
- 网络设备监控和控制
- 实时数据采集系统
- 分布式系统间的轻量级通信
- 需要简单可靠 UDP 通信的各种应用
这个类提供了一个完整且健壮的 UDP 通信解决方案,可以直接集成到 Qt 项目中使用。
完整代码
UDPCommunication.h
#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
#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);
}
}