Qt 网络编程 udp通信

news2024/10/6 8:14:14

学习目标:使用udp通信

前置环境

运行环境:qt creator 4.12

学习内容

UDP 协议基础知识
1、UDP(用户数据报协议)是轻量的、不可靠的、面向数据报、无连接的协议,用于可靠性要求不高的场合。两个应用程序之间进行UDP 通信不需先建立持久的 socket 连接,UDP 每次发送数据报都需要指定目标地址和端口。

2.ÙDP 报文没有可靠性保证、顺序保证和流量控制字段等,可靠性一较差。但是正因为 UDP 协议的控制选项较少在数据传输过程中延迟小、数据传输效率高,适合对可靠性要求不高的应用程序,或者可以保障可靠性的应用程序,如 DNS、TFTP、SNMP 等。

3、UDP 报头由 4个域组成,其中每个域各占用 2 个字节,具体包括
源端口号、目标端口号、数据包长度、校验值。端口号有效范围0--65535,假设端口号大于 49151的端口都代表动态端口

4、QUdpSocket类从QAbstractSocket类继承 基本跟QTcpSocket共用大部分的接口函数,主要区别在于 QUdpSocket 以数据报传输数据,不是以连续的数据流,发送方发送数据报使用函数QUdpSocket::writeDataGram(),数据报长度一般不超过 512 个字节,每个数据报包含发送方和接收方的 IP 地址和端口等数据信息。

QUdpSocket是Qt中用于UDP网络通信的类,它提供了以下一些常用的成员函数:

  1. bind(const QHostAddress &address, quint16 port): 绑定到指定的地址和端口。

  2. bind(quint16 port, BindMode mode = DefaultForPlatform): 绑定到指定的端口,并设置绑定模式。

  3. writeDatagram(const QByteArray &datagram, const QHostAddress &host, quint16 port): 将指定的数据报发送到指定的主机和端口。

  4. writeDatagram(const char *data, qint64 size, const QHostAddress &host, quint16 port): 将指定大小的数据发送到指定的主机和端口。

  5. readDatagram(char *data, qint64 maxSize, QHostAddress *address = nullptr, quint16 *port = nullptr): 从接收缓冲区中读取一个数据报,并将其存储在指定的缓冲区中。

  6. pendingDatagramSize(): 返回下一个待读取的数据报的大小。

  7. hasPendingDatagrams(): 检查是否有待读取的数据报。

  8. joinMulticastGroup(const QHostAddress &groupAddress): 加入一个多播组。

  9. leaveMulticastGroup(const QHostAddress &groupAddress): 退出一个多播组。

  10. setMulticastInterface(const QNetworkInterface &interface): 设置用于多播的网络接口。

  11. multicastInterface(): 返回用于多播的网络接口。

  12. setSocketOption(SocketOption option, const QVariant &value): 设置套接字选项。

  13. socketOption(SocketOption option): 返回指定的套接字选项的值。

  14. state(): 返回套接字的当前状态。

  15. error(): 返回最近一次发生的错误。

  16. abort() 用于中断或终止当前的 UDP 网络操作。可以确保 QUdpSocket 实例回到一个干净、可重用的状态,而不会产生任何残留的网络操作。需要注意的是,abort() 函数只会中断当前正在进行的操作,而不会关闭套接字本身。如果需要彻底关闭套接字,可以调用 close() 函数。

    1. 立即中断正在进行的任何 UDP 发送或接收操作。

    2. 清空内部缓冲区,丢弃所有待发送或待接收的数据。

    3. 将套接字的状态设置为 QAbstractSocket::UnconnectedState

这些成员函数涵盖了UDP网络编程的各个方面,包括数据发送、数据接收、多播管理、套接字选项设置等。使用这些函数可以方便地实现UDP通信的各种功能。

实现项目

Qt udp通讯编程

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    //获取当前主机ip  放到ip选项栏
    QHostInfo info =QHostInfo::fromName(QHostInfo::localHostName());
    QList<QHostAddress> addrs=info.addresses();
    if(!addrs.empty()){
        foreach(const QHostAddress& addr,addrs){
            if(addr.protocol()==QAbstractSocket::IPv4Protocol){
                ui->plainTextEdit->appendPlainText("本机当前ipv4:"+addr.toString());
                ui->tarip->addItem(addr.toString());
            }
        }
    }


    udpsocket=new QUdpSocket(this);

    ui->pushButton->setEnabled(true);
    ui->pushButton_3->setEnabled(false);

    //用作消息到达 处理消息
    // QObject::connect(udpsocket,SIGNAL(readyRead()),this,SLOT(UdpSockerRecvData())); 老版本Qt4.0语法糖 5.0弃用但是仍然可使用

    //QObject::connect(udpsocket,SIGNAL(QUdpSocket::readyRead()),this,SLOT(MainWindow::UdpSockerRecvData())); 新版本5.0 误区点
    //新版本5.0
    QObject:: connect(udpsocket, &QUdpSocket::readyRead, this, &MainWindow::UdpSockerRecvData);
}
void MainWindow::UdpSockerRecvData(){
    while(udpsocket->hasPendingDatagrams())
       {
           QByteArray datagrams;

           datagrams.resize(udpsocket->pendingDatagramSize());

           QHostAddress paddress;
           quint16 pport;

           // 通过readDatagram()此函数读取数据报,
           udpsocket->readDatagram(datagrams.data(),datagrams.size(),&paddress,&pport);

           QString strs=datagrams.data();
           QString peer="[From:"+paddress.toString()+":"+QString::number(pport)+"]:";

           ui->plainTextEdit->appendPlainText(peer+strs);

           qDebug()<<"UdpSockerRecvData:"<<peer;
       }
}

MainWindow::~MainWindow()
{
    delete ui;
    udpsocket->close();
    delete udpsocket;
}


void MainWindow::on_pushButton_clicked()//绑定端口
{
    QString ip=ui->tarip->currentText();
    qint16 port =ui->curport->value();

    if(udpsocket->bind(QHostAddress(ip),port)){
        ui->plainTextEdit->appendPlainText("**********绑定成功**********");
        ui->plainTextEdit->appendPlainText("$$$$$$$$$$绑定端口$$$$$$$$$$:"+QString::number(udpsocket->localPort()));
        ui->pushButton->setEnabled(false);
        ui->pushButton_3->setEnabled(true);
        qDebug()<<"绑定端口:"<<port;

    }else ui->plainTextEdit->appendPlainText("**********绑定失败**********");
}

void MainWindow::on_pushButton_3_clicked()//解除绑定端口
{
    qDebug()<<"解除绑定端口:"<<udpsocket->localPort();
    udpsocket->abort();
    ui->pushButton->setEnabled(true);
    ui->pushButton_3->setEnabled(false);
    ui->plainTextEdit->appendPlainText("**********已经停止服务**********");
}

void MainWindow::on_pushButton_2_clicked()//发送数据
{
     // 获取目标IP地址 端口 发送消息内容
    QString targetip=ui->tarip->currentText();
    uint16_t targetport =ui->tarport->value();
    QString msg =ui->editmsg->text();
    qDebug()<<"发送数据:"<<targetip<<targetport;
    QByteArray send =msg.toUtf8();
    // 发送数据报信息
    udpsocket->writeDatagram(send,QHostAddress(targetip),targetport);
    ui->plainTextEdit->appendPlainText("[out]:"+msg);
    ui->editmsg->clear();
}

void MainWindow::on_pushButton_4_clicked()//广播发送
{
    qint16 tarport =ui->tarport->value();
    QString msg =ui->editmsg->text();
    QByteArray send =msg.toUtf8();

    udpsocket->writeDatagram(send,QHostAddress::Broadcast,tarport);
    ui->plainTextEdit->appendPlainText("[broadcast out]:"+msg);
    ui->editmsg->clear();

    ui->editmsg->setFocus(); // 将光标焦点定位到编辑框控件
}

 总结

  1. 获取本地IP地址:

    • 通过 QHostInfo::fromName(QHostInfo::localHostName()) 获取本地主机信息
    • 遍历 QHostInfo::addresses() 中的地址,找到 IPv4 协议的地址
    • 将这些地址添加到 tarip 下拉框中供用户选择
  2. 创建 UDP 套接字:

    • 使用 QUdpSocket 类创建 UDP 套接字实例
    • 将 readyRead 信号连接到 UdpSockerRecvData 槽函数,用于处理接收到的数据
  3. 绑定 UDP 端口:

    • 在 on_pushButton_clicked 函数中,获取用户选择的 IP 地址和端口
    • 使用 udpsocket->bind(QHostAddress(ip), port) 绑定 UDP 套接字
    • 根据绑定结果更新 UI 状态和按钮可用性
  4. 接收 UDP 数据报:

    • 在 UdpSockerRecvData 槽函数中,通过 udpsocket->hasPendingDatagrams() 检查是否有待处理的数据报
    • 使用 udpsocket->readDatagram() 读取数据报,获取发送方地址和端口
    • 将接收到的消息显示在 plainTextEdit 窗口中
  5. 发送 UDP 数据报:

    • 在 on_pushButton_2_clicked 函数中,获取用户输入的目标 IP 地址、端口和消息
    • 使用 udpsocket->writeDatagram() 将消息发送到指定的目标
    • 在 plainTextEdit 窗口中显示发送的消息
  6. 广播 UDP 数据报:

    • 在 on_pushButton_4_clicked 函数中,获取用户输入的目标端口和消息
    • 使用 udpsocket->writeDatagram(data, QHostAddress::Broadcast, port) 将消息广播到所有客户端
    • 在 plainTextEdit 窗口中显示广播的消息
  7. 资源清理:

    • 在 MainWindow 析构函数中,关闭 UDP 套接字并删除实例
    • 确保资源得到正确释放,避免内存泄漏
最后附上源代码链接
对您有帮助的话,帮忙点个star

34-udpSocket · jbjnb/Qt demo - 码云 - 开源中国 (gitee.com)

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【IT领域新生必看】解密Java中的静态方法与实例方法:小白也能轻松掌握的全方位指南

文章目录 引言什么是静态方法&#xff1f;定义和使用静态方法示例&#xff1a; 静态方法的特点示例&#xff1a; 什么是实例方法&#xff1f;定义和使用实例方法示例&#xff1a; 实例方法的特点示例&#xff1a; 静态方法与实例方法的区别作用范围示例&#xff1a; 访问权限示…

宁德时代天行发布,商用车超充时代来临

近日&#xff0c;宁德时代正式推出商用动力电池品牌——“宁德时代天行”&#xff0c;同时发布“宁德时代天行轻型商用车&#xff08;L&#xff09;-超充版”和“宁德时代天行轻型商用车&#xff08;L&#xff09;-长续航版”两款产品&#xff0c;可实现4C超充能力和500km的实况…

14-38 剑和诗人12 - RAG+ 思维链 ⇒ 检索增强思维(RAT)

在快速发展的 NLP 和 LLM 领域&#xff0c;研究人员不断探索新技术来增强这些模型的功能。其中一种备受关注的技术是检索增强生成 (RAG) 方法&#xff0c;它将 LLM 的生成能力与从外部来源检索相关信息的能力相结合。然而&#xff0c;最近一项名为检索增强思维 (RAT) 的创新通过…

计算机网络(2

计算机网络续 一. 网络编程 网络编程, 指网络上的主机, 通过不同的进程, 以编程的方式实现网络通信(或网络数据传输). 即便是同一个主机, 只要不同进程, 基于网络来传输数据, 也属于网络编程. 二. 网络编程套接字(socket) socket: 操作系统提供的网络编程的 API 称作 “soc…

免杀笔记 ----> DLL注入

这段时间我们暂时没什么事情干的话我们就继续更新我们的免杀笔记力&#xff01;&#xff01;&#xff01; &#xff1a;今天我们讲DLL注入 目录 1.DLL注入 2.直接加载DLL&#xff1f; 3.远程线程注入 获取Handle 远程申请内存空间 将我们的CS的DLL加载入内存 创建远程线…

C语言 | Leetcode C语言题解之第218题天际线问题

题目&#xff1a; 题解&#xff1a; struct pair {int first, second; };struct Heap {struct pair* heap;int heapSize;bool (*cmp)(struct pair*, struct pair*); };void init(struct Heap* obj, int n, bool (*cmp)(struct pair*, struct pair*)) {obj->heap malloc(si…

Midjourney对图片细微调整和下载保存

点击v2是对第二图片细微调整。 点击u3对第3张图片进行放大。 保存图片: 对点击u3放大的图片&#xff0c;双击 , 右键保存图片

antd通过监听change方法实现表格分页查询功能

<script setup> import {computed, onMounted, ref} from "vue"; import axios from "axios";const columns [{name: 姓名,dataIndex: name,key: name,},{name: 性别,dataIndex: gender,key: gender,},{title: 年龄,dataIndex: age,key: age,},{tit…

江苏徐州SAP代理商有哪些?怎么选择?

在数字化浪潮席卷全球的今天&#xff0c;企业对于高效、智能的管理系统需求日益迫切。SAP作为全球领先的企业管理软件解决方案提供商&#xff0c;其产品在市场上享有极高的声誉。而在江苏徐州&#xff0c;哲讯智能科技作为SAP的代理商&#xff0c;以其专业的技术实力和优质的服…

配置基于不同端口的虚拟主机

更改配置文件&#xff0c;添加三个不同端口的虚拟主机 <directory /www> allowoverride none require all granted </directory><virtualhost 192.168.209.136:80> documentroot /www servername 192.168.209.136 </virtualhost><virtualhost 192.…

idea中没有显示‘‘Spring‘‘一栏 (已解决)

第一步: 随便找一个Bean(即直接或者间接使用Component的类) 第二步: 找到左边的图标, 右键这个图标, 然后选择如下选项: 第三步: 成功 然后就成功了, 可以看到具体的bean了以及其bean的关系图等.

数据库-多表设计 多表查询

多表设计 一对多 一对多关系实现&#xff1a;在数据库表中多的一方&#xff0c;添加字段&#xff0c;来关联一的一方的主键 外键约束 -- 创建表时指定 create table 表名(字段名 数据类型,...[constraint] [外键名称] foreign key (外键字段名) references 主表…

InetAddress.getLocalHost().getHostAddress()阻塞导致整个微服务崩溃

InetAddress.getLocalHost().getHostAddress()阻塞导致整个微服务崩溃 import java.net.InetAddress;public class GetHostIp {public static void main(String[] args) {try {long start System.currentTimeMillis();String ipAddress InetAddress.getLocalHost().getHostA…

(一)优化算法-遗传算法

目录 前言 一、什么是遗传算法&#xff1f; &#xff08;一&#xff09;基本结构 &#xff08;二&#xff09;遗传操作 二、仿真过程 &#xff08;一&#xff09;主程序部分 &#xff08;二&#xff09;选择函数 &#xff08;三&#xff09;交叉函数 &#xff08;四&a…

2024年加密货币市场展望:L1、L2、LSD、Web3 和 GameFi 板块的全面分析与预测

随着区块链技术的快速发展&#xff0c;加密货币市场在2024年继续展现出蓬勃的生机和创新的潜力。本文将深入分析L1、L2、LSD、Web3和GameFi这五大板块的发展趋势和预测&#xff0c;帮助投资者和爱好者更好地理解和把握市场机遇。 一、L1&#xff1a;基础层协议的持续进化 L1&a…

最新全平台无人直播硬改XCMS系统,支持任何平台

软件功能: 改虚拟摄像头为真实摄像头&#xff0c;改真实麦克风&#xff0c;图层去重、镜头晃动、增加噪点去重、随机播放辅音&#xff0c;两条音轨帮助音频去重、随机音效、随机播放速度&#xff0c;直播源实时转播等等.防违规&#xff0c;防非实时 设备需求: 电脑&#xf…

万界星空科技机械加工行业MES解决方案

机械加工行业作为制造业的重要组成部分&#xff0c;面临着生产效率、成本控制和产品质量提升等多重挑战。为了应对这些挑战&#xff0c;引入并实施制造执行系统&#xff08;MES&#xff09;成为了行业的必然选择。本文将详细介绍一种针对机械加工行业的MES解决方案&#xff0c;…

IT入门知识第八部分《人工智能》(9/10)

1.引言 在当今数字化时代&#xff0c;人工智能&#xff08;AI&#xff09;和机器学习&#xff08;ML&#xff09;已成为推动技术革新的关键力量。它们不仅改变了我们与机器的互动方式&#xff0c;还极大地拓展了解决问题的可能性。本文将深入探讨人工智能和机器学习的基础&…

全新桌面编辑器

目录 前言 一、链接 ONLYOFFICE 8.1版本 官网下载链接&#xff1a; ONLYOFFICE 在线工具&#xff1a; 下载版本推荐&#xff1a; 二、使用体验 1. 界面设计&#xff1a; 2. 文档编辑功能&#xff1a; 3. 电子表格功能&#xff1a; 4. 演示文稿功能&#xff1a; 5.PDF编…

在centos7上部署mysql8.0

1.安装MySQL的话会和MariaDB的文件冲突&#xff0c;所以需要先卸载掉MariaDB。查看是否安装mariadb rpm -qa | grep mariadb 2. 卸载mariadb rpm -e --nodeps 查看到的文件名 3.下载MySQL安装包 MySQL官网下载地址: MySQL :: Download MySQL Community Serverhttps://dev.mys…