文章目录
-
- [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 服务器和客户端都可以相互发送数据,不需要建立连接。