第六章 QT基础:5、QT的UDP网络编程

在 Qt 中,QUdpSocket 类用于实现基于 UDP 协议的网络通信。UDP(用户数据报协议)是一种无连接的协议,与 TCP 不同,它不需要建立连接,因此它的传输速度较快,但也不保证数据的可靠传输。


1. Qt UDP 编程概述

UDP 是一种无连接的协议,在网络上发送数据时不需要与接收方建立连接,数据直接发送到目标地址的指定端口。由于其无连接性,UDP 具有较低的延迟和较高的传输效率,但也无法保证数据的可靠性。

Qt 提供了 QUdpSocket 类来实现 UDP 网络编程。它支持绑定本地端口、接收数据报和发送数据报。

2. QUdpSocket 类的常用方法

  • bind():将本地套接字绑定到指定端口,开始监听该端口上的数据报。

  • writeDatagram():发送数据报到指定的地址和端口。

  • hasPendingDatagrams():检查是否有待处理的接收数据报。

  • readDatagram():读取接收到的一个数据报。

  • close():关闭 UDP 套接字。

3. 代码示例(带详细注释)

下面是一个使用 QUdpSocket 进行简单的 UDP 网络编程的示例,功能包括接收数据、发送数据以及端口绑定。

cpp 复制代码
#include "widget.h"
#include "ui_widget.h"
#include <QMessageBox>

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    // 创建 UDP 套接字
    udpSocket = new QUdpSocket(this);  // 使用 this 作为父对象
}

Widget::~Widget()
{
    delete ui;  // 删除 UI 对象
}

// 槽函数,用于处理接收到的数据报
void Widget::readyRead_slot()
{
    // 检查是否有待处理的数据报
    while (udpSocket->hasPendingDatagrams()) {
        QByteArray array;
        // 根据待处理数据报的大小调整数组的大小
        array.resize(udpSocket->pendingDatagramSize());
        // 读取数据报
        udpSocket->readDatagram(array.data(), array.size());

        // 将接收到的字节数组转换为 QString 类型,以便显示
        QString buf = QString::fromUtf8(array);
        // 将接收到的消息显示在 UI 的接收框中
        ui->recvEdit->appendPlainText(buf);
    }
}

// 点击 "打开" 按钮后绑定端口
void Widget::on_openBt_clicked()
{
    bool ok;
    // 从界面中获取输入的端口号,并尝试将其转换为 quint16 类型
    quint16 localPort = ui->localPort->text().toUInt(&ok); 

    // 如果端口号转换失败或端口号为 0,则弹出警告框提示用户
    if (!ok || localPort == 0) {
        QMessageBox::warning(this, "警告", "请输入有效的端口号");
        return;
    }

    // 绑定端口号到本地套接字
    if (udpSocket->bind(localPort)) {
        // 绑定成功,弹出信息框提示用户
        QMessageBox::information(this, "提示", "成功绑定端口");
    } else {
        // 绑定失败,弹出错误信息框
        QMessageBox::critical(this, "错误", "绑定端口失败,请检查端口是否被占用");
    }

    // 连接信号与槽,当数据报到达时触发 readyRead_slot
    connect(udpSocket, SIGNAL(readyRead()), this, SLOT(readyRead_slot()));
}

// 点击 "关闭" 按钮后关闭 UDP 套接字
void Widget::on_closeBt_clicked()
{
    udpSocket->close();  // 关闭套接字,停止接收数据
}

// 点击 "发送" 按钮后发送数据
void Widget::on_sendBt_clicked()
{
    quint16 port;
    QString sendbuf;
    QHostAddress address;

    // 从界面获取目标 IP 地址并设置
    address.setAddress(ui->aimIP->text());
    // 从界面获取要发送的文本
    sendbuf = ui->sendEdit->text();
    // 从界面获取目标端口号
    port = ui->aimPort->text().toUInt();

    // 使用 writeDatagram() 发送数据报
    udpSocket->writeDatagram(sendbuf.toUtf8(), address, port);
}

4. 代码逐行解释

4.1 初始化套接字
cpp 复制代码
udpSocket = new QUdpSocket(this);  // 创建 UDP 套接字对象,并将当前窗口作为父对象
  • 这里我们创建了一个 QUdpSocket 对象来进行 UDP 通信。this 作为父对象传入,确保在 Widget 被销毁时,udpSocket 也会被正确清理。
4.2 接收数据(readyRead_slot)
cpp 复制代码
while (udpSocket->hasPendingDatagrams()) {
    QByteArray array;
    array.resize(udpSocket->pendingDatagramSize());
    udpSocket->readDatagram(array.data(), array.size());
    QString buf = QString::fromUtf8(array);
    ui->recvEdit->appendPlainText(buf);
}
  • hasPendingDatagrams():检查是否有待接收的数据报。

  • readDatagram():读取接收到的一个数据报,并将数据存储到 array 中。

  • 将接收到的字节数据 array 转换为 QString,然后显示在界面上的文本框中。

4.3 打开端口并绑定(on_openBt_clicked)
cpp 复制代码
quint16 localPort = ui->localPort->text().toUInt(&ok);
if (!ok || localPort == 0) {
    QMessageBox::warning(this, "警告", "请输入有效的端口号");
    return;
}
if (udpSocket->bind(localPort)) {
    QMessageBox::information(this, "提示", "成功绑定端口");
} else {
    QMessageBox::critical(this, "错误", "绑定端口失败,请检查端口是否被占用");
}
  • 从界面的文本框中获取本地端口号,并尝试将其转换为整数类型。

  • 调用 bind() 方法绑定指定的端口,如果成功则弹出提示框。

4.4 发送数据(on_sendBt_clicked)
cpp 复制代码
udpSocket->writeDatagram(sendbuf.toUtf8(), address, port);
  • 获取目标 IP 地址、端口号以及要发送的消息内容。

  • 使用 writeDatagram() 方法将数据报发送到指定的目标 IP 和端口。

4.5 关闭 UDP 套接字(on_closeBt_clicked)
cpp 复制代码
udpSocket->close();  // 关闭 UDP 套接字
  • 调用 close() 方法关闭 UDP 套接字,停止接收数据。

5. Qt 中的信号与槽

Qt 使用信号与槽机制来实现事件驱动编程。当某个事件发生时(如按钮点击、数据到达等),会触发一个信号,信号会连接到一个槽(函数),从而执行相应的操作。

在本例中,当接收到数据时,readyRead() 信号会被触发,并调用 readyRead_slot() 槽函数来处理接收到的数据。

cpp 复制代码
connect(udpSocket, SIGNAL(readyRead()), this, SLOT(readyRead_slot()));

最后实现:

!\[Pasted image 20250422161717.png]

6. 总结

通过 QUdpSocket 类,Qt 提供了一种简便的方式来进行 UDP 网络通信。本示例展示了如何实现一个简单的 UDP 客户端,能够绑定端口、接收数据报、发送数据报,并且关闭 UDP 套接字。使用 Qt 进行 UDP 编程非常直观,尤其适用于实时性较高的应用,如实时聊天、传感器数据采集等。

相关推荐
Quz2 天前
QML Hello World 入门示例
qt
xcyxiner5 天前
DicomViewer (dcmtk读取dcm文件)5
qt
xcyxiner6 天前
DicomViewer (后台线程处理文件)4
qt
xcyxiner6 天前
DicomViewer (添加模型类)3
qt
xcyxiner7 天前
DicomViewer (目录调整) 2
qt
xcyxiner7 天前
dcmtk vtk vtk-dicom(gdcm) 编译(debug) v2
qt
网络研究院9 天前
2026年网络安全
网络·安全·法律·法规·趋势·发展
酣大智9 天前
ARP代理--工作原理
运维·网络·arp·arp代理
treesforest9 天前
AI安全系统如何识别异常访问?IP风险识别正在成为关键能力
网络·人工智能·tcp/ip·安全·web安全
shushangyun_9 天前
2026年快消品B2B系统推荐:支持终端门店订货、促销政策自动化的工具?
java·运维·网络·数据库·人工智能·spring·自动化