在 Qt 中实现 UDP 通信主要使用 QUdpSocket
类。以下是 UDP 通信的详细实现步骤和示例代码:
一、UDP 通信基础
- 无连接协议:不需要建立持久连接
- 数据报模式:以独立数据包(datagram)形式发送
- 适用场景:实时性要求高、允许少量丢包(如视频流、游戏、传感器数据)
二、核心类 QUdpSocket
1. 发送数据流程
// 创建 socket 对象
QUdpSocket *udpSocket = new QUdpSocket(this);
// 准备数据
QByteArray datagram = "Hello UDP!";
QHostAddress targetAddress = QHostAddress("192.168.1.100");
quint16 targetPort = 1234;
// 发送数据报(单播)
qint64 bytesSent = udpSocket->writeDatagram(datagram, targetAddress, targetPort);
// 广播示例(发送到所有子网设备)
// udpSocket->writeDatagram(datagram, QHostAddress::Broadcast, 1234);
2. 接收数据流程
// 创建 socket 并绑定端口
QUdpSocket *udpSocket = new QUdpSocket(this);
bool bindResult = udpSocket->bind(1234); // 绑定接收端口
// 连接信号槽
connect(udpSocket, &QUdpSocket::readyRead, [=]() {
while (udpSocket->hasPendingDatagrams()) {
QByteArray datagram;
datagram.resize(udpSocket->pendingDatagramSize());
QHostAddress senderAddress;
quint16 senderPort;
udpSocket->readDatagram(datagram.data(), datagram.size(),
&senderAddress, &senderPort);
qDebug() << "Received from" << senderAddress.toString()
<< ":" << senderPort
<< "Data:" << datagram;
}
});
// 错误处理
connect(udpSocket, &QUdpSocket::errorOccurred, [=](QAbstractSocket::SocketError error){
qDebug() << "UDP Error:" << udpSocket->errorString();
});
三、多播(组播)实现
// 加入多播组
QHostAddress multicastGroup("239.255.43.21");
udpSocket->joinMulticastGroup(multicastGroup);
// 设置TTL(生存时间)
udpSocket->setSocketOption(QAbstractSocket::MulticastTtlOption, 1);
// 发送多播数据
udpSocket->writeDatagram(datagram, multicastGroup, 1234);
// 离开多播组
udpSocket->leaveMulticastGroup(multicastGroup);
四、完整示例
发送端类
class UdpSender : public QObject {
public:
UdpSender(QObject *parent = nullptr) : QObject(parent) {
socket = new QUdpSocket(this);
}
void sendMessage(const QString &message, const QHostAddress &target, quint16 port) {
QByteArray data = message.toUtf8();
socket->writeDatagram(data, target, port);
}
private:
QUdpSocket *socket;
};
接收端类
class UdpReceiver : public QObject {
Q_OBJECT
public:
UdpReceiver(quint16 port, QObject *parent = nullptr)
: QObject(parent) {
socket = new QUdpSocket(this);
connect(socket, &QUdpSocket::readyRead, this, &UdpReceiver::processPendingDatagrams);
socket->bind(port);
}
private slots:
void processPendingDatagrams() {
while (socket->hasPendingDatagrams()) {
QByteArray datagram;
datagram.resize(socket->pendingDatagramSize());
QHostAddress sender;
quint16 senderPort;
socket->readDatagram(datagram.data(), datagram.size(), &sender, &senderPort);
emit messageReceived(QString::fromUtf8(datagram),
sender.toString(),
senderPort);
}
}
signals:
void messageReceived(const QString &message,
const QString &senderIp,
quint16 senderPort);
private:
QUdpSocket *socket;
};
五、注意事项
-
在
.pro
文件中添加网络模块:QT += network
-
UDP 数据报最大长度通常为 65507 字节(IPv4)
-
处理数据时考虑:
- 数据可能分片到达
- 可能收到不完整数据包
- 需要自行处理数据校验
-
广播地址:
- 受限广播:
255.255.255.255
- 子网广播:
192.168.1.255
(具体取决于子网掩码)
- 受限广播:
通过以上实现,您可以轻松在 Qt 应用中完成 UDP 通信功能。根据具体需求选择单播、广播或多播模式,并注意处理可能的网络异常情况。