C++ Qt开发:QUdpSocket网络通信组件

Qt 是一个跨平台C++图形界面开发库,利用Qt可以快速开发跨平台窗体应用程序,在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置,实现图形化开发极大的方便了开发效率,本章将重点介绍如何运用QUdpSocket组件实现基于UDP的网络通信功能。

QTcpSocket组件功能类似,QUdpSocket组件是 Qt 中用于实现用户数据报协议(UDP,User Datagram Protocol)通信的类。UDP 是一种无连接的、不可靠的数据传输协议,它不保证数据包的顺序和可靠性,但具有低延迟和简单的特点。

以下是 QUdpSocket 类的完整函数及其简要解释:

函数描述
QUdpSocket(QObject *parent = nullptr)构造函数,创建一个新的 QUdpSocket 对象。
~QUdpSocket()析构函数,释放 QUdpSocket 对象及其资源。
void bind(const QHostAddress &address, quint16 port, BindMode mode = DefaultForPlatform)将套接字绑定到指定的本地地址和端口。
void close()关闭套接字。
bool joinMulticastGroup(const QHostAddress &groupAddress, const QNetworkInterface &iface = QNetworkInterface())加入多播组。
bool leaveMulticastGroup(const QHostAddress &groupAddress, const QNetworkInterface &iface = QNetworkInterface())离开多播组。
qint64 pendingDatagramSize() const返回下一个待读取的数据报的大小。
qint64 readDatagram(char *data, qint64 maxSize, QHostAddress *address = nullptr, quint16 *port = nullptr)读取数据报。
QByteArray readDatagram(qint64 maxSize, QHostAddress *address = nullptr, quint16 *port = nullptr)读取数据报,返回 QByteArray 对象。
qint64 writeDatagram(const char *data, qint64 size, const QHostAddress &address, quint16 port)发送数据报。
qint64 writeDatagram(const QByteArray &datagram, const QHostAddress &address, quint16 port)发送数据报,接受 QByteArray 对象。
QAbstractSocket::SocketState state() const返回套接字的当前状态。
QAbstractSocket::SocketType socketType() const返回套接字的类型。
bool isValid() const如果套接字有效,则返回 true;否则返回 false
int error() const返回套接字的当前错误代码。
QHostAddress localAddress() const返回本地地址。
quint16 localPort() const返回本地端口。
int readBufferSize() const返回读取缓冲区的大小。
void setReadBufferSize(int size)设置读取缓冲区的大小。
QNetworkInterface multicastInterface() const返回多播组的网络接口。
void setMulticastInterface(const QNetworkInterface &iface)设置多播组的网络接口。
bool hasPendingDatagrams() const如果有待读取的数据报,则返回 true;否则返回 false
bool isReadable() const如果套接字可读,则返回 true;否则返回 false
bool isWritable() const如果套接字可写,则返回 true;否则返回 false
bool setSocketDescriptor(int socketDescriptor, QUdpSocket::SocketState socketState = ConnectedState, QIODevice::OpenMode openMode = ReadWrite)设置套接字描述符。
int socketDescriptor() const返回套接字描述符。
bool waitForReadyRead(int msecs = 30000)等待套接字可读取数据。
bool waitForBytesWritten(int msecs = 30000)等待套接字已写入指定字节数的数据。
void ignoreSslErrors(const QList<QSslError> &errors)忽略 SSL 错误。
void abort()强制关闭套接字。
QNetworkProxy proxy() const返回套接字的代理设置。
void setProxy(const QNetworkProxy &networkProxy)设置套接字的代理设置。
QString errorString() const返回套接字的错误消息字符串。

这些函数提供了在 UDP 通信中使用 QUdpSocket 的各种功能,包括绑定、发送和接收数据报、设置和获取套接字的状态等。

1.1 初始化部分

在初始化部分我们首先通过new QUdpSocket来实现创建UDP对象,QUdpSocket 构造函数的函数原型如下:

QUdpSocket::QUdpSocket(QObject * parent = nullptr)

如上构造函数创建一个新的 QUdpSocket 对象。如果提供了 parent 参数,则会将新创建的 QUdpSocket 对象添加到 parent 对象的子对象列表中,并且在 parent 对象被销毁时自动销毁 QUdpSocket 对象。如果没有提供 parent 参数,则 QUdpSocket 对象将不会有父对象,并且需要手动管理其生命周期。

初始化结束后,则下一步需要调用bind()bind() 函数是 QUdpSocket 类的一个成员函数,用于将套接字绑定到特定的本地地址和端口。它的函数原型如下:

void QUdpSocket::bind(const QHostAddress &address, quint16 port, BindMode mode = DefaultForPlatform)
  • address:要绑定的本地地址,通常是 QHostAddress::Any,表示绑定到所有可用的网络接口。
  • port:要绑定的本地端口号。
  • mode:绑定模式,指定套接字的行为。默认值是 DefaultForPlatform,表示使用平台默认的绑定模式。

该函数允许 QUdpSocket 在本地网络接口上监听传入的数据报。一旦调用了 bind() 函数,QUdpSocket 就可以接收来自指定地址和端口的数据报。

在调用 bind() 函数之后,如果成功绑定了指定的地址和端口,套接字将处于 BoundState 状态。如果出现错误,可以通过检查 error() 函数获取错误代码,并通过 errorString() 函数获取错误消息。

接着我们通过connect()函数依次绑定套接字到stateChanged状态改变信号,以及readyRead()读取信号上,这段初始化代码如下所示;

MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);udpSocket=new QUdpSocket(this);// 生成随机整数 包含2000 - 不包含65534int randomInt = QRandomGenerator::global()->bounded(2000, 65534);if(udpSocket->bind(randomInt)){this->setWindowTitle(this->windowTitle() + " | 地址: " + getLocalAddress() + " 绑定端口:" + QString::number(udpSocket->localPort()));}connect(udpSocket,SIGNAL(stateChanged(QAbstractSocket::SocketState)),this,SLOT(onSocketStateChange(QAbstractSocket::SocketState)));onSocketStateChange(udpSocket->state());connect(udpSocket,SIGNAL(readyRead()),this,SLOT(onSocketReadyRead()));
}

接着切换到读取信号所对应的槽函数上,onSocketReadyRead是我们自定义的一个槽,该槽函数功能如下所示;

// 读取收到的数据报
void MainWindow::onSocketReadyRead()
{while(udpSocket->hasPendingDatagrams()){QByteArray datagram;datagram.resize(udpSocket->pendingDatagramSize());QHostAddress peerAddr;quint16 peerPort;udpSocket->readDatagram(datagram.data(),datagram.size(),&peerAddr,&peerPort);QString str=datagram.data();QString peer="[消息来自 " + peerAddr.toString()+":"+QString::number(peerPort)+"] | ";ui->plainTextEdit->appendPlainText(peer+str);}
}

首先在代码中调用pendingDatagramSize函数,pendingDatagramSize()QUdpSocket 类的一个成员函数,用于获取下一个待读取的数据报的大小。它的函数原型如下:

qint64 QUdpSocket::pendingDatagramSize() const

该函数返回一个 qint64 类型的值,表示下一个待读取的数据报的大小(以字节为单位)。如果没有待读取的数据报,或者发生了错误,该函数将返回 -1。

通常,可以在调用 readDatagram() 函数之前调用 pendingDatagramSize() 函数来获取下一个待读取的数据报的大小。这样可以为数据缓冲区分配正确大小的空间,以确保完整地读取数据报。

当有了待读取字节后,接着就可以直接通过调用readDatagram函数来从套接字中读取数据报,readDatagram()QUdpSocket 类的一个成员函数,它有几个重载形式,其中最常用的是:

qint64 QUdpSocket::readDatagram(char * data, qint64 maxSize, QHostAddress * address = nullptr, quint16 * port = nullptr)

该函数用于读取数据报并将其存储到指定的缓冲区 data 中,最多读取 maxSize 个字节的数据。可选参数 addressport 用于返回数据报的源地址和端口号。如果不需要这些信息,可以将它们设置为 nullptr

函数返回实际读取的字节数,如果发生错误,返回 -1。要查看错误信息,可以使用 error()errorString() 函数。

另外,还有一个更简单的重载形式:

QByteArray QUdpSocket::readDatagram(qint64 maxSize, QHostAddress * address = nullptr, quint16 * port = nullptr)

这个重载函数直接返回一个 QByteArray 对象,其中包含了读取的数据报。

1.2 单播与广播消息

单播(Unicast)和广播(Broadcast)是网络通信中常见的两种数据传输方式,它们在数据包的传输范围和目标数量上有所不同。

单播(Unicast)

单播是一种一对一的通信方式,其中数据包从一个发送者传输到一个接收者。在单播通信中,数据包只发送到目标主机的网络接口,并且只有目标主机能够接收和处理这个数据包。

  • 一对一通信:每个数据包只有一个发送者和一个接收者。
  • 目标明确:数据包只发送到特定的目标主机,其他主机不会接收到这个数据包。
  • 点到点通信:适用于直接通信的场景,如客户端与服务器之间的通信。

当按钮发送消息被点击后,则是一种单播模式,通常该模式需要得到目标地址与端口号,并通过调用writeDatagram来实现数据的发送,该函数通过传入三个参数,分别是发送字符串,目标地址与目标端口来实现一对一推送。

void MainWindow::on_pushButton_clicked()
{QHostAddress targetAddr(ui->lineEdit_addr->text());QString portString = ui->lineEdit_port->text();quint16 targetPort = portString.toUShort();QString msg=ui->lineEdit_msg->text();QByteArray str=msg.toUtf8();// 发送数据报udpSocket->writeDatagram(str,targetAddr,targetPort);ui->plainTextEdit->appendPlainText("[单播消息] | " + msg);
}
广播(Broadcast)

广播是一种一对多的通信方式,其中数据包从一个发送者传输到同一网络中的所有主机。在广播通信中,数据包被发送到网络中的所有主机,并且所有的主机都能够接收和处理这个数据包。

  • 一对多通信:每个数据包有一个发送者,但可以有多个接收者。
  • 目标不明确:数据包被发送到网络中的所有主机,不需要知道接收者的具体地址。
  • 广播域:在局域网中进行广播,只有在同一广播域内的主机才能接收到广播消息。
  • 网络负载:在大型网络中使用广播可能会产生大量的网络流量,影响网络性能。

当按钮广播消息被点击后,则同样是调用writeDatagram函数与,唯一的区别在于第二个参数并未指定地址,而是使用了QHostAddress::Broadcast来代替,意味着只要端口是一致的则对所有的客户推送消息,其他保持不变。

void MainWindow::on_pushButton_2_clicked()
{// 广播地址QString portString = ui->lineEdit_port->text();quint16 targetPort = portString.toUShort();QString  msg=ui->lineEdit_msg->text();QByteArray str=msg.toUtf8();udpSocket->writeDatagram(str,QHostAddress::Broadcast,targetPort);ui->plainTextEdit->appendPlainText("[广播消息] | " + msg);
}

读者可自行运行两次客户端,此时的端口将会随机分配,当指定对端端口后就可以向其发送数据,如下图所示;具体实现细节,请参考文章附件。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/279025.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Windows server 2008 R2 在VMware虚拟机上的安装

Windows server 2008 R2 在VMware虚拟机上的安装 准备工作VMware 新建并配置虚拟机安装和启动Windows server 2008 R2 准备工作 Windows server 2008 R2 ISO镜像的下载&#xff1a;Windows server 2008 R2 ISO VMware 新建并配置虚拟机 第一步&#xff0c;点击新建虚拟机 第…

sqllab第二十关通关笔记

知识点&#xff1a; cookie注入 可以进行url解析错误注入传参位置 get请求post请求cookie传参 输入admin admin进行登录&#xff0c;抓取当前数据包 通过放包发现是一个302跳转的响应包&#xff0c;页面只有一个 I Love Cookies&#xff1b;没什么信息 通过点击页面上方的按钮…

3.Gen<I>Cam文件配置

Gen<I>Cam踩坑指南 我使用的是大恒usb相机&#xff0c;第一步到其官网下载大恒软件安装包,安装完成后图标如图所示&#xff0c;之后连接相机&#xff0c;打开软件&#xff0c;相机显示一切正常。之后查看软件的安装目录如图&#xff0c;发现有GenICam和GenTL两个文件&am…

智能ai文生视频,文生动漫小程序,系统搭建开发

目录 前言&#xff1a; 一、文生动漫系统搭建常规步骤 二、文生漫画是怎么操作的 总结&#xff1a; 前言&#xff1a; 小说推文是继短视频之后的又一个黄金赛道&#xff0c;它最大的特点就是&#xff0c;有一个人观看了你推荐的小说就有一份收益。那么使用系统小说转漫功能…

如何选择合适的数据可视化工具?

如果是入门级的数据可视化工具&#xff0c;使用Excel插件就足够了&#xff01; Excel插件&#xff0c;tusimpleBI 是一款 Excel 图表插件&#xff0c;提供超过120项图表功能&#xff0c;帮助用户制作各种 Excel 所没有的高级图表&#xff0c;轻轻松松一键出图。 它能够制作10…

《计算机视觉中的深度学习》之目标检测算法原理

参考&#xff1a;《计算机视觉中的深度学习》 概述 目标检测的挑战&#xff1a; 减少目标定位的准确度减少背景干扰提高目标定位的准确度 目标检测系统常用评价指标&#xff1a;检测速度和精度 提高精度&#xff1a;有效排除背景&#xff0c;光照和噪声的影响 提高检测速度…

D咖自助咖啡机:颠覆传统,重塑咖啡体验?

在咖啡文化日益蓬勃发展的今天&#xff0c;传统的咖啡消费方式已经不能完全满足人们对于咖啡品质和体验的追求。在这个背景下&#xff0c;商用自助咖啡机以其独特的优势和创新&#xff0c;正在颠覆传统的咖啡消费模式&#xff0c;为咖啡爱好者们打开了全新的咖啡体验之门。D咖今…

多模态:Vary-toy

文章目录 前言一、模型结构二、数据工程总结 前言 Vary的提出让大模型在OCR相关任务的能力有了很大突破&#xff0c;通过提出额外的视觉词汇表模块来弥补单一CLIP编码能力的不足&#xff0c;详情可参考我之前的文章——多模态&#xff1a;Vary。 最近Vary的团队开发了一个更小…

深度学习_卷积

卷积 卷积&#xff08;Convolution&#xff09;是数学和计算机科学中的一个重要概念&#xff0c;特别在信号处理和图像处理中应用广泛。在信号处理领域&#xff0c;卷积是两个函数之间的一种数学操作&#xff0c;它表示两个函数的重叠部分的积分量。 在图像处理中&#xff0c…

数据结构之链式二叉树

当我们初步了解二叉树后 我们就可以进一步去深入学习二叉树了 1.链式二叉树的遍历 这里我们先去定义链式二叉树的结构 分为两个指针 一左一右 他们分别指向左子树和右子树 typedef int BTDataType;typedef struct BinaryTreeNode {BTDataType data;struct BinartTreeNod…

Django templates 存放html目录

模板 一概述 模板由两部分组成&#xff0c;一部分是HTML代码&#xff0c;一部分是逻辑控制代码&#xff08;变量&#xff0c;标签&#xff0c;过滤器&#xff09; 作用&#xff1a;可以通过一些逻辑控制代码减少一些重复的操作更快速的生成HTML代码&#xff0c;并且实现简单的…

php 对接Mintegral汇量海外广告平台收益接口Reporting API

今天对接的是Mintegral广告reporting api接口&#xff0c;拉取广告收益回来自己做统计。记录分享给大家 首先是文档地址,进入到Mintegral后台就能看到文档地址以及参数&#xff1a; 文档地址&#xff1a;https://cdn-adn-https.rayjump.com/cdn-adn/reporting_api/MintegralRA.…

蓝桥杯刷题(十一)

1.卡片 反向思考&#xff0c;看k种卡片可以分给几位同学 代码 n int(input()) k 1 while k*(k1)<2*n:k1 print(k)2.美丽的2 代码 def f(x)->bool:while x:if x%102:return Truex//10return False cnt 0 for i in range(1,2021):if f(i):cnt1 print(cnt)3.单词分析 …

因聚而生 数智有为丨软通动力携子公司鸿湖万联亮相华为中国合作伙伴大会2024

3月14日&#xff0c;以“因聚而生 数智有为”为主题的“华为中国合作伙伴大会2024”在深圳隆重开幕。作为华为的重要合作伙伴和本次大会钻石级&#xff08;最高级&#xff09;合作伙伴&#xff0c;软通动力深度参与本次盛会&#xff0c;携前沿数智化技术成果和与华为的联合解决…

SpringCloud Bus 消息总线

一、前言 接下来是开展一系列的 SpringCloud 的学习之旅&#xff0c;从传统的模块之间调用&#xff0c;一步步的升级为 SpringCloud 模块之间的调用&#xff0c;此篇文章为第八篇&#xff0c;即介绍 Bus 消息总线。 二、概述 2.1 遗留的问题 在上一篇文章的最后&#xff0c;我…

整型数组按个位值排序 - 华为OD统一考试(C卷)

OD统一考试&#xff08;C卷&#xff09; 分值&#xff1a; 100分 题解&#xff1a; Java / Python / C 题目描述 给定一个非空数组(列表)&#xff0c;其元素数据类型为整型&#xff0c;请按照数组元素十进制最低位从小到大进行排序&#xff0c;十进制最低位相同的元素&#xf…

计算机网络——物理层(奈氏准则和香农定理)

计算机网络——物理层&#xff08;奈氏准则和香农定理&#xff09; 失真码间串扰奈氏准则&#xff08;奈奎斯特定理&#xff09;极限数据率 噪声信噪比香农定理奈氏准则和香农定理的区别 前面我们已经了解一些数据通信的基本知识&#xff0c;没有看过上一篇得小伙伴可以点击这里…

网络安全框架和云安全参考架构介绍

目录 一、网络安全框架 1.1 概述 1.2 IATF框架 1.2.1 框架来源 1.2.2 框架结构图 1.2.3 框架内容 1.2.3.1 人&#xff08;People&#xff09; 1.2.3.2 技术&#xff08;Technology&#xff09; 1.2.3.3 操作&#xff08;Operation&#xff09; 1.3 NIST网络安全框架 …

【一】【单片机】有关LED的实验

点亮一个LED灯 根据LED模块原理图&#xff0c;我们可以知道&#xff0c;通过控制P20、P21...P27这八个位置的高低电平&#xff0c;可以实现D1~D8八个LED灯的亮灭。VCC接的是高电平&#xff0c;如果P20接的是低电平&#xff0c;那么D1就可以亮。如果P20接的是高电平&#xff0c;…

stm32-模拟数字转化器ADC

接线图&#xff1a; #include "stm32f10x.h" // Device header//1: 开启RCC时钟&#xff0c;包括ADC和GPIO的时钟//2&#xff1a;配置GPIO将GPIO配置为模拟输入模式//3&#xff1a;配置多路开关将左边的通道接入到规则组中//4&#xff1a;配置ADC转…