当前位置: 首页 > news >正文

QT的UDP

定义
UDP是一种无连接的传输层协议。它位于TCP/IP协议栈的传输层,为应用层提供了一种不需要建立连接就可以直接发送数据报的服务。UDP的主要目的是在IP网络上快速、高效地传输数据,而不保证数据的可靠传输。

工作原理
在UDP通信中,发送方应用程序将数据封装成UDP数据报,然后直接发送给接收方。UDP数据报包括一个UDP头部和应用层数据。UDP头部包含源端口号、目的端口号、数据报长度和校验和等信息。
源端口号是发送方应用程序的端口号,用于标识发送方的应用程序;目的端口号是接收方应用程序的端口号,用于标识接收方的应用程序。数据报长度表示整个UDP数据报的长度,包括头部和数据部分。校验和用于检查UDP数据报在传输过程中是否出现错误。
当接收方收到UDP数据报后,根据目的端口号将数据报交给对应的应用程序。UDP不进行数据的确认、排序、重传等操作,这些操作由应用层自己来处理。

特点
无连接:UDP在发送数据之前不需要建立连接。这使得UDP的开销较小,因为它不需要像TCP那样进行三次握手来建立连接,也不需要进行四次挥手来释放连接。例如,在一些实时性要求很高的多媒体应用(如网络视频会议)中,UDP可以快速地将视频数据发送出去,减少建立连接的延迟。
不可靠传输:UDP不保证数据的可靠传输。它不会对丢失的数据报进行重传,也不会对乱序的数据报进行排序。如果数据报在传输过程中丢失或者出现错误,UDP不会主动进行修复。这种不可靠性使得UDP在一些对可靠性要求不高的场景下很有优势,比如在一些简单的查询服务(如DNS查询)中,即使偶尔丢失一个查询请求,也不会对整个系统产生严重的影响。
速度快:由于UDP没有复杂的错误检查和恢复机制,数据传输速度相对较快。它适合于对实时性要求高、对数据完整性要求相对较低的应用场景。例如,在一些在线游戏场景中,玩家的操作指令通过UDP快速传输,即使偶尔丢失一些指令数据,也不会对游戏的整体体验产生太大的影响,因为游戏可以根据后续的操作指令进行一定的补偿。

应用场景
实时音频/视频通信:像Skype、Zoom等视频会议软件在传输音频和视频数据时会使用UDP。因为在这些应用中,实时性是至关重要的。即使数据有少量丢失,也不会对语音和视频的质量产生致命的影响。而且UDP能够快速地将数据发送出去,减少延迟,保证通信的流畅性。
DNS(域名系统):DNS查询通常使用UDP。当客户端向DNS服务器查询域名对应的IP地址时,UDP可以快速地将查询请求发送给DNS服务器,并且DNS查询对数据的可靠性要求相对较低,即使偶尔丢失一个查询请求,客户端可以重新发起查询。
在线游戏:在一些简单的在线游戏中,如一些休闲小游戏,游戏服务器和客户端之间的交互数据(如玩家的操作指令、游戏状态更新等)通过UDP传输。UDP能够快速地将这些数据发送出去,保证游戏的实时性

QT实现步奏
在Qt中实现UDP同步收发数据,主要依赖于QUdpSocket类。QUdpSocket提供了基于UDP协议的网络通信功能。同步收发数据意味着在发送数据后,程序会等待接收响应,直到数据被接收或者超时。这种模式在一些简单的查询 - 响应场景中很有用。以下是实现UDP同步收发数据的基本步骤和代码示例:

  1. 包含必要的头文件
    cpp
    #include
    #include
    #include
  2. 创建QUdpSocket对象
    cpp
    QUdpSocket *udpSocket = new QUdpSocket(this);
  3. 配置UDP套接字
    绑定本地端口:如果需要接收数据,需要绑定一个本地端口。
    设置超时机制:可以通过QTimer来实现超时机制。
  4. 发送数据
    使用QUdpSocket::writeDatagram()方法发送数据。
  5. 接收数据
    使用QUdpSocket::readDatagram()方法接收数据。
    在超时时间内等待数据接收完成。
  6. 处理超时
    如果在超时时间内没有收到数据,可以认为接收失败

QT案列
UDP 接收端(服务器):监听 12345 端口,打印收到的数据
UDP 发送端(客户端):向 127.0.0.1:12345 发送 “Hello UDP”
整个工程采用 Qt6 + CMake;如用 qmake,仅需把 CMakeLists.txt 换成 .pro 即可。

1,工程架构
QtUdpDemo/
├ CMakeLists.txt
├ src/
│ ├ main.cpp // 启动界面(两个按钮:发送 / 接收)
│ ├ UdpReceiver.h/.cpp // 接收端
│ └ UdpSender.h/.cpp // 发送端

2.CMakeLists.txt

cmake_minimum_required(VERSION 3.16)
project(QtUdpDemo LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
find_package(Qt6 REQUIRED COMPONENTS Core Widgets Network)
qt_standard_project_setup()
qt_add_executable(QtUdpDemosrc/main.cppsrc/UdpReceiver.cppsrc/UdpSender.cpp
)
target_link_libraries(QtUdpDemo Qt6::Core Qt6::Widgets Qt6::Network)

3.UdpReceiver.h / UdpReceiver.cpp

// UdpReceiver.h
#pragma once
#include <QWidget>
#include <QUdpSocket>
#include <QTextEdit>class UdpReceiver : public QWidget {Q_OBJECT
public:explicit UdpReceiver(QWidget *parent = nullptr);
private slots:void readPendingDatagrams();
private:QUdpSocket *socket;QTextEdit  *log;
};
// UdpReceiver.cpp
#include "UdpReceiver.h"
#include <QVBoxLayout>
#include <QHostAddress>UdpReceiver::UdpReceiver(QWidget *parent): QWidget(parent), socket(new QUdpSocket(this)), log(new QTextEdit(this)) {setWindowTitle("UDP Receiver - port 12345");QVBoxLayout *lay = new QVBoxLayout(this);lay->addWidget(log);bool ok = socket->bind(QHostAddress::Any, 12345);log->append(ok ? "Bind OK" : socket->errorString());connect(socket, &QUdpSocket::readyRead,this,   &UdpReceiver::readPendingDatagrams);
}void UdpReceiver::readPendingDatagrams() {while (socket->hasPendingDatagrams()) {QNetworkDatagram dgram = socket->receiveDatagram();log->append(QString("From %1:%2  ->  %3").arg(dgram.senderAddress().toString()).arg(dgram.senderPort()).arg(QString(dgram.data())));}
}

4.dpSender.h / UdpSender.cpp

// UdpSender.h
#pragma once
#include <QWidget>
#include <QUdpSocket>
class QLineEdit;
class QPushButton;class UdpSender : public QWidget {Q_OBJECT
public:explicit UdpSender(QWidget *parent = nullptr);
private slots:void sendDatagram();
private:QUdpSocket *socket;QLineEdit  *input;QPushButton *btn;
};
// UdpSender.cpp
#include "UdpSender.h"
#include <QVBoxLayout>
#include <QHostAddress>UdpSender::UdpSender(QWidget *parent): QWidget(parent), socket(new QUdpSocket(this)) {setWindowTitle("UDP Sender");input = new QLineEdit("Hello UDP");btn   = new QPushButton("Send");QVBoxLayout *lay = new QVBoxLayout(this);lay->addWidget(input);lay->addWidget(btn);connect(btn, &QPushButton::clicked, this, &UdpSender::sendDatagram);
}void UdpSender::sendDatagram() {QByteArray data = input->text().toUtf8();socket->writeDatagram(data, QHostAddress("127.0.0.1"), 12345);
}

5.main.cpp(启动两个窗口)

#include <QApplication>
#include "UdpReceiver.h"
#include "UdpSender.h"int main(int argc, char *argv[]) {QApplication a(argc, argv);UdpReceiver recv;recv.show();UdpSender send;send.show();return a.exec();
}
Qt类 / 函数作用
QUdpSocket::bind()绑定本地端口,开始监听
writeDatagram()发送数据报
readyRead() 信号有数据到达时触发
receiveDatagram()读取完整数据报 + 对端信息
QNetworkDatagramQt6 推荐的新数据结构,一次拿到数据 + 元信息
http://www.dtcms.com/a/314235.html

相关文章:

  • 【数据结构入门】链表
  • Solidity智能合约开发全攻略
  • Java基础-斗地主游戏
  • ArrayDeque双端队列--底层原理可视化
  • ubuntu修改时区
  • 【HZ-T536开发板免费体验】Cangjie Magic调用视觉语言大模型(VLM)真香,是不是可以没有YOLO和OCR了?
  • 通用 PDF 文件流 OCR 到文本 API 接口
  • 使用 Aspose.OCR 将图像文本转换为可编辑文本
  • 基础14-Java集合框架:掌握List、Set和Map的使用
  • 十字滑台:精密制造的“心脏“如何跳动?
  • 耘瞳科技国产化点云处理软件,开启智能化三维测量新时代
  • [机器学习]01-构建简单的贝叶斯分类器
  • 抓包相关知识学习
  • 项目复盘:Arena Of Furnace
  • vtkSSAAPass代码解析
  • [自动化Adapt] 回放策略 | AI模型驱动程序
  • Python异常捕获全指南
  • 智慧泵房赋能二次供水互联网化:物联网驱动下的全场景解决方案
  • Solidity全局变量与安全实践指南
  • Linux 文件与目录属性管理总结
  • 设备能力指标(CP/CPK)
  • C盘空间清理
  • JVM学习日记(十六)Day16——性能监控与调优(三)
  • AgxOrin平台JetPack5.x版本fix multi-cam race condition 补丁
  • 【Conda】常用指令操作
  • 机器学习——决策树(DecisionTree)+ 过采样 + 交叉验证 案例:电信客户流失数据
  • VAE学习笔记
  • Linux 网络深度剖析:传输层协议 UDP/TCP 原理详解
  • 【STM32】GPIO的输入输出
  • 正点原子STM32MP257开发板移植ubuntu24.04根文件系统(带桌面版)