第六章 QT根本:5、QT的UDP网络编程

打印 上一主题 下一主题

主题 1587|帖子 1587|积分 4761

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

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

1. Qt UDP 编程概述

UDP 是一种无毗连的协议,在网络上发送数据时不需要与接收方创建毗连,数据直接发送到目标地址的指定端口。由于其无毗连性,UDP 具有较低的延迟和较高的传输效率,但也无法保证数据的可靠性。
Qt 提供了 QUdpSocket 类来实现 UDP 网络编程。它支持绑定本地端口、接收数据报和发送数据报。
2. QUdpSocket 类的常用方法



  • bind():将本地套接字绑定到指定端口,开始监听该端口上的数据报。
  • writeDatagram():发送数据报到指定的地址和端口。
  • hasPendingDatagrams():检查是否有待处置惩罚的接收数据报。
  • readDatagram():读取接收到的一个数据报。
  • close():关闭 UDP 套接字。
3. 代码示例(带具体解释)

下面是一个使用 QUdpSocket 进行简单的 UDP 网络编程的示例,功能包罗接收数据、发送数据以及端口绑定。
  1. #include "widget.h"
  2. #include "ui_widget.h"
  3. #include <QMessageBox>
  4. Widget::Widget(QWidget *parent) :
  5.     QWidget(parent),
  6.     ui(new Ui::Widget)
  7. {
  8.     ui->setupUi(this);
  9.     // 创建 UDP 套接字
  10.     udpSocket = new QUdpSocket(this);  // 使用 this 作为父对象
  11. }
  12. Widget::~Widget()
  13. {
  14.     delete ui;  // 删除 UI 对象
  15. }
  16. // 槽函数,用于处理接收到的数据报
  17. void Widget::readyRead_slot()
  18. {
  19.     // 检查是否有待处理的数据报
  20.     while (udpSocket->hasPendingDatagrams()) {
  21.         QByteArray array;
  22.         // 根据待处理数据报的大小调整数组的大小
  23.         array.resize(udpSocket->pendingDatagramSize());
  24.         // 读取数据报
  25.         udpSocket->readDatagram(array.data(), array.size());
  26.         // 将接收到的字节数组转换为 QString 类型,以便显示
  27.         QString buf = QString::fromUtf8(array);
  28.         // 将接收到的消息显示在 UI 的接收框中
  29.         ui->recvEdit->appendPlainText(buf);
  30.     }
  31. }
  32. // 点击 "打开" 按钮后绑定端口
  33. void Widget::on_openBt_clicked()
  34. {
  35.     bool ok;
  36.     // 从界面中获取输入的端口号,并尝试将其转换为 quint16 类型
  37.     quint16 localPort = ui->localPort->text().toUInt(&ok);
  38.     // 如果端口号转换失败或端口号为 0,则弹出警告框提示用户
  39.     if (!ok || localPort == 0) {
  40.         QMessageBox::warning(this, "警告", "请输入有效的端口号");
  41.         return;
  42.     }
  43.     // 绑定端口号到本地套接字
  44.     if (udpSocket->bind(localPort)) {
  45.         // 绑定成功,弹出信息框提示用户
  46.         QMessageBox::information(this, "提示", "成功绑定端口");
  47.     } else {
  48.         // 绑定失败,弹出错误信息框
  49.         QMessageBox::critical(this, "错误", "绑定端口失败,请检查端口是否被占用");
  50.     }
  51.     // 连接信号与槽,当数据报到达时触发 readyRead_slot
  52.     connect(udpSocket, SIGNAL(readyRead()), this, SLOT(readyRead_slot()));
  53. }
  54. // 点击 "关闭" 按钮后关闭 UDP 套接字
  55. void Widget::on_closeBt_clicked()
  56. {
  57.     udpSocket->close();  // 关闭套接字,停止接收数据
  58. }
  59. // 点击 "发送" 按钮后发送数据
  60. void Widget::on_sendBt_clicked()
  61. {
  62.     quint16 port;
  63.     QString sendbuf;
  64.     QHostAddress address;
  65.     // 从界面获取目标 IP 地址并设置
  66.     address.setAddress(ui->aimIP->text());
  67.     // 从界面获取要发送的文本
  68.     sendbuf = ui->sendEdit->text();
  69.     // 从界面获取目标端口号
  70.     port = ui->aimPort->text().toUInt();
  71.     // 使用 writeDatagram() 发送数据报
  72.     udpSocket->writeDatagram(sendbuf.toUtf8(), address, port);
  73. }
复制代码

4. 代码逐行解释

4.1 初始化套接字

  1. udpSocket = new QUdpSocket(this);  // 创建 UDP 套接字对象,并将当前窗口作为父对象
复制代码


  • 这里我们创建了一个 QUdpSocket 对象来进行 UDP 通信。this 作为父对象传入,确保在 Widget 被烧毁时,udpSocket 也会被正确清理。
4.2 接收数据(readyRead_slot)

  1. while (udpSocket->hasPendingDatagrams()) {
  2.     QByteArray array;
  3.     array.resize(udpSocket->pendingDatagramSize());
  4.     udpSocket->readDatagram(array.data(), array.size());
  5.     QString buf = QString::fromUtf8(array);
  6.     ui->recvEdit->appendPlainText(buf);
  7. }
复制代码


  • hasPendingDatagrams():检查是否有待接收的数据报。
  • readDatagram():读取接收到的一个数据报,并将数据存储到 array 中。
  • 将接收到的字节数据 array 转换为 QString,然后表如今界面上的文本框中。
4.3 打开端口并绑定(on_openBt_clicked)

  1. quint16 localPort = ui->localPort->text().toUInt(&ok);
  2. if (!ok || localPort == 0) {
  3.     QMessageBox::warning(this, "警告", "请输入有效的端口号");
  4.     return;
  5. }
  6. if (udpSocket->bind(localPort)) {
  7.     QMessageBox::information(this, "提示", "成功绑定端口");
  8. } else {
  9.     QMessageBox::critical(this, "错误", "绑定端口失败,请检查端口是否被占用");
  10. }
复制代码


  • 从界面的文本框中获取本地端标语,并实验将其转换为整数类型。
  • 调用 bind() 方法绑定指定的端口,如果成功则弹出提示框。
4.4 发送数据(on_sendBt_clicked)

  1. udpSocket->writeDatagram(sendbuf.toUtf8(), address, port);
复制代码


  • 获取目标 IP 地址、端标语以及要发送的消息内容。
  • 使用 writeDatagram() 方法将数据报发送到指定的目标 IP 和端口。
4.5 关闭 UDP 套接字(on_closeBt_clicked)

  1. udpSocket->close();  // 关闭 UDP 套接字
复制代码


  • 调用 close() 方法关闭 UDP 套接字,制止接收数据。

5. Qt 中的信号与槽

Qt 使用信号与槽机制来实现事件驱动编程。当某个事件发生时(如按钮点击、数据到达等),会触发一个信号,信号会毗连到一个槽(函数),从而执行相应的操作。
在本例中,当接收到数据时,readyRead() 信号会被触发,并调用 readyRead_slot() 槽函数来处置惩罚接收到的数据。
  1. connect(udpSocket, SIGNAL(readyRead()), this, SLOT(readyRead_slot()));
复制代码

最后实现:
![[Pasted image 20250422161717.png]]
6. 总结

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

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

用户云卷云舒

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表