【QT网络编程】实现UDP协议通信

news2025/1/10 17:22:38

文章目录

  • 概要:本期主要讲解QT中对UDP协议通信的实现。
  • 一、UDP协议通信
  • 二、Qt中UDP协议的处理
    • 1.QUdpSocket
  • 三、Qt实现UDP通信
    • 1.客户端
    • 2.服务器端
  • 结尾

概要:本期主要讲解QT中对UDP协议通信的实现。

一、UDP协议通信

Internet 协议集支持一个无连接的传输协议,该协议称为用户数据报协议(UDP,User Datagram Protocol)。UDP 为应用程序提供了一种无需建立连接就可以发送封装的 IP 数据包的方法。RFC 768 描述了 UDP。
在这里插入图片描述
UDP协议根据消息传送模式可以分为:单播(Unicast)、组播(Multicast)和广播(Broadcast)。

  1. 单播:一个UDP客户端发出的数据报只发送到另一个指定地址和端口的UDP客户端,是一对一的数据传输
  2. 组播:也称多播,UDP客户端加入到另一个组播IP地址指定的多播组,成员向组播地址发送的数据报组内成员都可以接收到,类似于QQ群功能。
  3. 广播:一个UDP客户端发出的数据报,在同一网络范围内其他所有的UDP客户端都可以收到

二、Qt中UDP协议的处理

Qt中提供了QUdpSocket类用于创建UDP套接字。

1.QUdpSocket

QUdpSocket类继承于QAbstractSocket,提供了UdpSocket套接字的创建、连接对位服务器、加组等。
在这里插入图片描述

三、Qt实现UDP通信

UDP通信是对等服务器间信息传递,其实不需要指定客户端和服务器端,但是为了便于理解,我在实现时仍然采用C-S的结构。
实现步骤如下:
创建UDP套接字 --> 绑定端口 --> 加组(区分消息传送模式) -->发送数据(区分消息传送模式) --> 接受数据

1.客户端

客户端实现发送数据。

#ifndef UDPCLIENT_H
#define UDPCLIENT_H

#include <QObject>
#include <QHostAddress>
#include <QUdpSocket>
#include <QDebug>
#include <QTimer>

class UDPClient :QObject
{
    Q_OBJECT
public:
    UDPClient();

    void InitSocket();//初始化UDP套接字

    void InitTimer();//初始化定时器

public slots:
    void SendData();//发送数据

private:
    QUdpSocket *mUdpSocket;//UDP套接字对象
    QHostAddress mGroupAddress;//组播地址
    QTimer *mTimer;//定时器对象
    int mType;//记录UDP消息传送模式 0:单播 1:广播 2:组播(多播)
};

#endif // UDPCLIENT_H
#include "udpclient.h"

UDPClient::UDPClient()
{
//    mType = 0;//Unicast
//    mType = 1;//Broadcast
    mType = 2;//Multicast
    InitSocket();
    InitTimer();

}

void UDPClient::InitSocket()
{
    mUdpSocket = new QUdpSocket;//初始化socket
    mGroupAddress.setAddress("239.2.2.222");//设置组播地址
    mUdpSocket->bind(6666);//绑定端口号
    if(mType == 2)
    {
        //组播的数据的生存期,数据报没跨1个路由就会减1.表示多播数据报只能在同一路由下的局域网内传播
        mUdpSocket->setSocketOption(QAbstractSocket::MulticastTtlOption,1);
    }
}

void UDPClient::InitTimer()
{
    mTimer = new QTimer;//初始化定时器
    connect(mTimer,&QTimer::timeout,this,[=]
    {
        SendData();
    });
    mTimer->start(1000);//每隔一秒发送一次数据
}

void UDPClient::SendData()
{
    QByteArray _data = "hello";
    if(mType == 0)//单播
    {
        QHostAddress _peerHostAddress = QHostAddress("10.0.0.177");//对位服务器IP
        quint16 _port = 6666;//对位服务器端口
        if(-1 !=mUdpSocket->writeDatagram(_data.data(),_data.size(),_peerHostAddress,_port))
        {
            qDebug()<< "Unicast ==> Send data : "<< _data<<endl;
        }
        mUdpSocket->flush();
    }
    else if(mType == 1)//广播
    {
        quint16 _port = 6666;//广播端口
        if(-1 !=mUdpSocket->writeDatagram(_data.data(),QHostAddress::Broadcast,_port))
        {
            qDebug()<< "Broadcast ==> Send data : "<< _data<<endl;
        }
        mUdpSocket->flush();
    }
    else if(mType == 2)//组播
    {
        quint16 _port = 8888;//组播端口
        if(-1 != mUdpSocket->writeDatagram(_data.data(),mGroupAddress,_port))
        {
            qDebug()<< "Multicast ==> Send data : "<< _data<<endl;
        }
        mUdpSocket->flush();
    }
    else
    {
        qDebug()<< "mType is error! "<<endl;
        return;
    }


}

2.服务器端

服务器端实现数据的接收。

#ifndef UDPSERVER_H
#define UDPSERVER_H

#include <QObject>
#include <QHostAddress>
#include <QUdpSocket>
#include <QDebug>

class UDPServer : QObject
{
    Q_OBJECT
public:
    UDPServer();
    void InitSocket();//初始化套接字

public slots:
    void ReadPendingDataframs();//读取消息

private:
    QUdpSocket *mUdpSocket;//UDP套接字
    QHostAddress mGroupAdress;//组播地址
    int mType; //记录UDP消息传送模式 0:单播 1:广播  2:组播(多播)
};

#endif // UDPSERVER_H
#include "udpserver.h"
UDPServer::UDPServer()
{
//    mType = 0;//Unicast
//    mType = 1;//Broadcast
    mType = 2;//Multicast
    InitSocket();

}

void UDPServer::InitSocket()
{
    //初始化socket,设置组播地址
    mUdpSocket = new QUdpSocket;
    mGroupAdress.setAddress("239.2.2.222");
    if(mType == 0 || mType == 1)
    {
        //绑定本地IP和端口号
        mUdpSocket->bind(6666);
    }
    else if(mType == 2)
    {
        if(mUdpSocket->bind(QHostAddress::AnyIPv4,8888,QUdpSocket::ShareAddress))
        {
            //加入组播地址
            mUdpSocket->joinMulticastGroup(mGroupAdress);
            qDebug()<<("Join Multicast Adrress [")<<mGroupAdress.toString()
                   <<("] Successful!")<<endl;
        }
    }
    else
    {
        qDebug()<< "mType is error! "<<endl;
        return;
    }

    connect(mUdpSocket,&QUdpSocket::readyRead,this,[=]{
        ReadPendingDataframs();
    });
}



void UDPServer::ReadPendingDataframs()
{
    QByteArray _data;
    _data.resize(mUdpSocket->pendingDatagramSize());
    if(mType == 0)//Unicast
    {
        QHostAddress *_peerHostAddress = new QHostAddress("10.0.0.32");
        quint16 _port = 6666;
        while(mUdpSocket->hasPendingDatagrams())
        {
            mUdpSocket->readDatagram(_data.data(),_data.size(),_peerHostAddress,&_port);//接收指定IP和端口的udp报文
            qDebug()<<"Unicast ==> Receive data : "<<QString::fromLatin1(_data)<<endl;
        }
    }
    else if(mType == 1)//Broadcast
    {
        QHostAddress _peerHostAddress;
        quint16 _port;
        while(mUdpSocket->hasPendingDatagrams())
        {
            mUdpSocket->readDatagram(_data.data(),_data.size(),&_peerHostAddress,&_port);//接收同一子网的udp报文
            qDebug()<<"Broadcast ==> Receive data : "<<QString::fromLatin1(_data)<<endl;
        }
    }
    else if(mType == 2)//Multicast
    {
        QHostAddress _peerHostAddress;
        quint16 _port;
        while(mUdpSocket->hasPendingDatagrams())
        {
            mUdpSocket->readDatagram(_data.data(),_data.size(),&_peerHostAddress,&_port);//接收同组的udp报文
            qDebug()<<"Multicast ==> Receive data : "<<QString::fromLatin1(_data)<<endl;
        }
    }
    else
    {
        qDebug()<< "mType is error! "<<endl;
        return;
    }
}

结尾

以上就是QT实现UDP协议通信的全部内容了,记得加上network模块:)

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

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

相关文章

SprintBoot打包及profile文件配置

打成Jar包 需要添加打包组件将项目中的资源、配置、依赖包打到一个jar包中&#xff0c;可以使用maven的package&#xff1b;运行: java -jar xxx(jar包名) 操作步骤 第一步: 引入Spring Boot打包插件 <!--打包的插件--> <build><!--修改jar的名字--><fi…

认识vite_vue3 初始化项目到打包

从0到1创建vite_vue3的项目背景效果vite介绍&#xff08;对比和vuecli的区别&#xff09;使用npm创建vitevitevuie3创建安装antdesignvite自动按需引入&#xff08;vite亮点&#xff09;请求代理proxy打包背景 vue2在使用过程中对象的响应式不好用新增属性的使用$set才能实现效…

FPGA 20个例程篇:20.USB2.0/RS232/LAN控制并行DAC输出任意频率正弦波、梯形波、三角波、方波(二)

通过上面的介绍相信大家对数字变频已经有了一个较为整体性的认识&#xff0c;下面笔者来对照XILINX的DDS IP核对数字变频技术展开更进一步的说明&#xff0c;做到了理论和实践很好地结合&#xff0c;这样大家再带入Modelsim进行仿真测试就不仅掌握了数字变频的理论知识&#xf…

【Linux】网络原理

本篇博客让我们一起来了解一下网络的基本原理 1.网络发展背景 关于网络发展的历史背景这种东西就不多bb了&#xff0c;网上很容易就能找到参考资料&#xff0c;我的专业性欠缺&#xff0c;文章参考意义也不大。这里只做简单说明。 网络发展经过了如下几个模式 独立模式&…

创建线程的三种方法

文章目录1、创建一个类实现Runnable接口&#xff0c;并重写run方法。2、创建一个类继承Thread类&#xff0c;并重写run方法。3、实现Callable接口&#xff0c;重写call()方法&#xff0c;这种方式可以通过FutureTask获取任务执行的返回值。4、run()方法和start()方法有什么区别…

14 Day:同步锁与操作系统输入输出

前言&#xff1a;在上一期的线程章节中&#xff0c;我们的线程输出貌似有大问题&#xff0c;今天我们便要来学习同步锁来解决这个问题&#xff0c;同时再次基础上拿下键盘输入&#xff0c;实现操作系统的输入和输出。从今天开始我们的操作系统不在是一块“看板”了&#xff01;…

Python|数学|贪心|数组|动态规划|单选记录:实现保留3位有效数字(四舍六入五成双规则)|用Python来创造一个提示用户输入数字的乘法表|最小路径和

1、实现保留3位有效数字&#xff08;四舍六入五成双规则&#xff09;&#xff08;数学&#xff0c;算法&#xff09; 贡献者&#xff1a;weixin_45782673 输入&#xff1a;1234 输出&#xff1a;1234 12 12.0 4 4.00 0.2 0.200 0.32 0.320 1.3 1.30 1.235 1.24 1.245 1.24 1.…

Docker 入门建议收藏 第一部分

一、Docker 是什么&#xff1f; Docker&#xff0c;翻译过来就是码头工人 Docker是一个开源的应用容器引擎&#xff0c;让开发者可以打包他们的应用以及依赖包到一个可抑制的容器中&#xff0c;然后发布到任何流行的Linux机器上&#xff0c;也可以实现虚拟化。容器完全使用沙盒…

JVM概览:内存空间与数据存储

核心的五个部分虚拟机栈&#xff1a;局部变量中基础类型数据、对象的引用存储的位置&#xff0c;线程独立的。堆&#xff1a;大量运行时对象都在这个区域存储&#xff0c;线程共享的。方法区&#xff1a;存储运行时代码、类变量、常量池、构造器等信息&#xff0c;线程共享。程…

ClassMix: Segmentation-Based Data Augmentation for Semi-Supervised Learning学习笔记

ClassMix相关介绍主要思想方法Mean-Teacher损失函数交叉熵损失标签污染实验实验反思参考资料相关介绍 从DAFormer溯源到这篇文章&#xff0c;ClassMix主要是集合了伪标签和一致性正则化&#xff0c;思想来源于CutMix那条研究路线&#xff0c;但是优化了CutMix中的标签污染的情…

使用 HTML5 轻松验证表单插件

下载:https://download.csdn.net/download/mo3408/87559594 效果图: 当您通过表单从人们那里收集信息时,必须应用某种验证。如果不这样做,可能会导致客户流失、数据库中的垃圾数据甚至网站的安全漏洞。从历史上看,构建表单验证一直很痛苦。在服务器端,全栈框架会为您处理…

【AI绘图学习笔记】深度前馈网络(一)

有关深度前馈网络的部分知识&#xff0c;我们已经在吴恩达的机器学习课程中有过了解了&#xff0c;本章主要是对《深度学习》花书中第六章&#xff1a;深度前馈网络的总结笔记。我希望你在看到这一章的时候&#xff0c;能回忆起机器学习课程中的一些环节或者细节&#xff0c;这…

【现代机器人学】学习笔记十一:抓握与操作

本章是比较独特的一章&#xff0c;相对于前面的内容&#xff0c;内容较为独立&#xff0c;主要描述的是力学相关的一些理论。因此&#xff0c;读者也完全不必根据题目产生一些不必要的幻想&#xff0c;认为似乎看完这章我就可以学会机器人抓取。不过&#xff0c;我仍然认为这章…

新入职的项目经理,如何击破权力微薄的困境?

“从此找到了上班的意义”这个话题最近登上了热搜&#xff0c;在“铜三铁四”的招聘季&#xff0c;大家停止了内卷&#xff0c;给自己安排得明明白白&#xff0c;每天上班的动力就是&#xff1a;充电、蹭网、干饭、灌水、睡午觉、上厕所。但咱项目经理们却没办法Get这些动力&am…

【UEFI基础】HOB介绍

综述 HOB的全称是Hand-Off Block&#xff0c;从名字上也可以看出来&#xff0c;它表示的是一种用于交接的数据。按照HOB的使用情况&#xff0c;可以将BIOS的启动阶段分为两个部分&#xff1a; HOB生成阶段&#xff08;HOB producer phase&#xff09;&#xff0c;用来创建和修…

PMP项目管理项目质量管理

目录1 项目质量管理概述2 规划质量管理3 管理质量4 控制质量1 项目质量管理概述 项目质量管理包括把组织的质量政策应用于规则、管理、控制项目和产品质量要求&#xff0c;以满足相关方目标的各个过程。项目质量管理还将以组织的名义支持过程的持续改进活动。 核心概念 质量是…

Elasticsearch:集群管理

在今天的文章中&#xff0c;我们应该学习如何管理我们的集群。 备份和分片分配是我们应该能够执行的基本任务。 分片分配过滤 Elasticsearch 将索引配到一个或多个分片中&#xff0c;我们可以将这些分片保存在特定的集群节点中。 例如&#xff0c;假设你有多个数据集群节点&am…

感应电机数学模型(电机控制应用基础系列)

电机在工业控制中的地位不言而喻&#xff0c;所以对电机模型的了解是我们理解各种算法的基础。这篇博客帮大家整理总结。张力控制离不开电机控制&#xff0c;有关张力控制的详细内容请参看下面的文章链接&#xff1a; PLC张力控制&#xff08;开环闭环算法分析&#xff09;_张…

字符函数和字符串函数详解(1)

目录前言strlen函数strlensizeofstrcpy函数strcat函数strcmp函数总结前言 最近要调整状态&#xff0c;写的文章质量不佳让大家失望&#xff0c;我现在也在反思我在做什么&#xff0c;我会什么&#xff0c;我学了什么。等我想明白的那天&#xff0c;我一定能跟大家顶峰相见的&a…

身份推理桌游

目录 sha人游戏&#xff08;天黑请闭眼&#xff09; &#xff08;1&#xff09;入门版 &#xff08;2&#xff09;标准版 &#xff08;3&#xff09;延伸版——百度百科 待更新 &#xff08;4&#xff09;延伸版——推理学院 待更新 狼人杀 1&#xff0c;基本玩法 2&am…