Qt Udp的组播(多播)、广播和单播

news2024/11/25 2:28:57

UDP通讯的基本概念和特点‌
UDP(User Datagram Protocol,用户数据报协议)是‌TCP/IP协议族中的一种无连接协议,主要用于那些对实时性要求较高而可靠性要求较低的应用场景。UDP的主要特点包括:

‌无连接‌:UDP在发送数据之前不需要建立连接,减少了建立连接的开销。
‌不保证可靠传输‌:UDP不提供数据传输的可靠性保证,数据可能会丢失或重复。
‌面向报文‌:UDP以独立的数据报形式发送数据,每个数据报都是独立的,并且保留了数据的边界。
‌首部开销小‌:UDP的首部开销非常小,只有8个字节,适合传输小数据包。
‌支持多种通信模式‌:UDP支持一对一、一对多、多对一和多对多的通信模式。
UDP通讯的实现步骤
‌创建套接字‌:使用socket()函数创建一个UDP套接字。
‌绑定地址‌:使用bind()函数将套接字与本地地址绑定。
‌发送数据‌:使用sendto()函数发送数据包,需要指定目的地址和端口。
‌接收数据‌:使用recvfrom()函数接收数据包,可以获取发送方的地址和端口信息。
‌关闭套接字‌:使用close()函数关闭套接字,释放资源。
UDP通讯的应用场景
由于UDP具有无连接、快速传输的特点,它非常适合用于那些对实时性要求较高而可靠性要求较低的应用场景,例如:

‌‌视频会议‌:视频流传输需要低延迟,UDP可以满足这一需求。
‌在线游戏‌:游戏中的实时交互需要快速的数据传输,UDP可以减少延迟。
‌实时监控‌:监控系统需要实时传输视频和报警信息,UDP可以提供快速的数据传输。
‌多媒体直播‌:直播需要低延迟和高带宽利用率,UDP可以满足这些要求。

单播
一个UDP客户端发送数据报到指定地址和端口的另一UDP客户端,是一对一的数据传输。
请添加图片描述
组播(多播)
是一点对多点的通信,IPv6没有采用IPv4中的组播术语,而是将广播看成是多播的一个特殊例子。
多播与单播步骤是一样的,只有IP地址有所区别。
多播的地址是特定的,D类地址用于多播。D类IP地址就是多播IP地址,即224.0.0.0至239.255.255.255之间的IP地址,并被划分为局部连接多播地址、预留多播地址和管理权限多播地址3类:
1,局部多播地址:在224.0.0.0~224.0.0.255之间,这是为路由协议和其他用途保留的地址,路由器并不转发属于此范围的IP包
2,预留多播地址:在224.0.1.0~238.255.255.255之间,可用于全球范围(如Internet)或网络协议。
3,管理权限多播地址:在239.0.0.0~239.255.255.255之间,可供组织内部使用,类似于私有IP地址,不能用于Internet,可限制多播范围。
请添加图片描述

广播
广播与组播是一样的,只是ip地址有所不同,而且不用加入指定的组。单播的数据只是收发数据的特定主机进行处理,组播在特定组之间进行处理,而广播的数据整个局域网都进行处理。
广播可以理解为一个人通过广播喇叭对在场的全体说话,这样做的好处是通话效率高,信息一下子就可以传递到全体。
广播在网络中的应用较多,如客户机通过DHCP自动获得IP地址的过程就是通过广播来实现的。但是同单播和多播相比,广播几乎占用了子网内网络的所有带宽。拿开会打一个比方吧,在会场上只能有一个人发言,想象一下如果所有的人同时都用麦克风发言,那会场上就会乱成一锅粥。
在IP网络中,广播地址用IP地址“255.255.255.255”来表示,这个IP地址代表同一子网内所有的IP地址。
请添加图片描述
代码:
.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QUdpSocket>
#include <QTimer>

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = nullptr);
    ~Widget();

    void unicastOpen();
public slots:
    void onSocketReadyRead();
private slots:
    void on_openbtn_clicked();

    void on_senbtn_clicked();

    void on_autoBox_clicked(bool checked);

    void on_leavebtn_clicked();

    void on_typebox_activated(int index);

private:
    Ui::Widget *ui;
    QUdpSocket *m_socket = nullptr;
    QTimer m_timer;
    bool m_joinFg = false;
    void multicastSendData();
    void multicastReadData();
    void multicastOpen();
    void multicastLeave();
    void broadcastSendData();
    void broadcastReadData();
    void broadcastOpen();
    void broadcastClose();
    void unicastClose();
    void unicastReadData();
    void unicastSendData();
    void open();
    void close();
    void readData();
    void sendData();
};

#endif // WIDGET_H

.cpp

#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
#include <QNetworkInterface>

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);

    ///单播
    //一个UDP客户端发送数据报到指定地址和端口的另一UDP客户端,是一对一的数据传输。
    ///组播(多播)
    /*是一点对多点的通信,IPv6没有采用IPv4中的组播术语,而是将广播看成是多播的一个特殊例子。
    多播与单播步骤是一样的,只有IP地址有所区别。
    多播的地址是特定的,D类地址用于多播。D类IP地址就是多播IP地址,即224.0.0.0至239.255.255.255之间的IP地址,并被划分为局部连接多播地址、预留多播地址和管理权限多播地址3类:
    1,局部多播地址:在224.0.0.0~224.0.0.255之间,这是为路由协议和其他用途保留的地址,路由器并不转发属于此范围的IP包
    2,预留多播地址:在224.0.1.0~238.255.255.255之间,可用于全球范围(如Internet)或网络协议。
    3,管理权限多播地址:在239.0.0.0~239.255.255.255之间,可供组织内部使用,类似于私有IP地址,不能用于Internet,可限制多播范围。*/
    ///广播
    /*广播与组播是一样的,只是ip地址有所不同,而且不用加入指定的组。单播的数据只是收发数据的特定主机进行处理,组播在特定组之间进行处理,而广播的数据整个局域网都进行处理。
    广播可以理解为一个人通过广播喇叭对在场的全体说话,这样做的好处是通话效率高,信息一下子就可以传递到全体。
    广播在网络中的应用较多,如客户机通过DHCP自动获得IP地址的过程就是通过广播来实现的。但是同单播和多播相比,广播几乎占用了子网内网络的所有带宽。拿开会打一个比方吧,在会场上只能有一个人发言,想象一下如果所有的人同时都用麦克风发言,那会场上就会乱成一锅粥。
    在IP网络中,广播地址用IP地址“255.255.255.255”来表示,这个IP地址代表同一子网内所有的IP地址。*/


    m_socket = new QUdpSocket(this);
    connect(m_socket,&QUdpSocket::readyRead,this,&Widget::onSocketReadyRead);
    connect(&m_timer,&QTimer::timeout,this,[=](){
        if (m_joinFg)
            on_senbtn_clicked();
    });

    ui->ipedit1->setEnabled(false);
}

Widget::~Widget()
{
    delete ui;
}

void Widget::on_openbtn_clicked()
{
    if (ui->typebox->currentIndex() == 0)
        multicastOpen();
    else if (ui->typebox->currentIndex() == 1)
        broadcastOpen();
    else if (ui->typebox->currentIndex() == 2)
        unicastOpen();
}
void Widget::on_leavebtn_clicked()
{
    if (ui->typebox->currentIndex() == 0)
        multicastLeave();
    else if (ui->typebox->currentIndex() == 1)
        broadcastClose();
    else if (ui->typebox->currentIndex() == 2)
        unicastClose();
}
void Widget::onSocketReadyRead()
{
    if (ui->typebox->currentIndex() == 0)
        multicastReadData();
    else if (ui->typebox->currentIndex() == 1)
        broadcastReadData();
    else if (ui->typebox->currentIndex() == 2)
        unicastReadData();
}
void Widget::on_senbtn_clicked()
{
    if (ui->typebox->currentIndex() == 0)
        multicastSendData();
    else if (ui->typebox->currentIndex() == 1)
        broadcastSendData();
    else if (ui->typebox->currentIndex() == 2)
        unicastSendData();
}


void Widget::multicastOpen()
{
    m_socket->setSocketOption(QAbstractSocket::MulticastTtlOption,100);

    QString ip = ui->ipedit1->text()+ui->ipedit2->text();
    int port = ui->portedit->text().toInt();
    if (m_socket->bind(QHostAddress::AnyIPv4,port,QUdpSocket::BindFlag::ShareAddress | QUdpSocket::BindFlag::ReuseAddressHint))
    {
        m_socket->joinMulticastGroup(QHostAddress(ip));
        QString msg = "加入组播"+ip+":"+ui->portedit->text();
        ui->msgedit->append(msg);
        m_joinFg = true;
        qDebug()<<msg;
    }
    else
    {
        ui->msgedit->append("加入组播失败");
        m_joinFg = false;
    }
}
void Widget::multicastLeave()
{
    QString ip = ui->ipedit1->text()+ui->ipedit2->text();
    m_socket->leaveMulticastGroup(QHostAddress(ip));
    m_socket->abort();
    ui->msgedit->append("退出组播");
    ui->autoBox->setChecked(false);
    m_joinFg = false;
    m_timer.stop();
}
void Widget::multicastReadData()
{
    while(m_socket->hasPendingDatagrams())
    {
        QByteArray datagram;
        datagram.resize(m_socket->pendingDatagramSize());
        QHostAddress peerAddr;
        quint16 peerPort;
        m_socket->readDatagram(datagram.data(),datagram.size(),&peerAddr,&peerPort);

        QString str=datagram.data();

        QString peer="[从 "+peerAddr.toString()+":"+QString::number(peerPort)+" 发送] ";

        ui->msgedit->append(peer+str);
        qDebug()<<peer+str;
    }
}
void Widget::multicastSendData()
{
    QString ip = ui->ipedit1->text()+ui->ipedit2->text();
    m_socket->writeDatagram(ui->sendedit->text().toUtf8(),QHostAddress(ip),ui->portedit->text().toInt());
}


void Widget::broadcastOpen()
{
    int port = ui->portedit->text().toInt();
    if (m_socket->bind(QHostAddress::AnyIPv4,port,QUdpSocket::BindFlag::ShareAddress | QUdpSocket::BindFlag::ReuseAddressHint))
    {
        QString msg = "打开广播"+ui->portedit->text();
        ui->msgedit->append(msg);
        m_joinFg = true;
        qDebug()<<msg;
    }
    else
    {
        ui->msgedit->append("打开广播失败");
        m_joinFg = false;
    }
}
void Widget::broadcastClose()
{
    m_socket->abort();
    ui->msgedit->append("退出广播");
    ui->autoBox->setChecked(false);
    m_joinFg = false;
    m_timer.stop();
}
void Widget::broadcastReadData()
{
    //读取数据
    while(m_socket->hasPendingDatagrams())//hasPendingDatagrams()如果至少有一个数据报等待读取,则返回true;
    {
        QByteArray datagram;
        datagram.resize(m_socket->pendingDatagramSize());
        QHostAddress peerAddr;
        quint16 peerPort;
        m_socket->readDatagram(datagram.data(),datagram.size(),&peerAddr,&peerPort);

        QString str=datagram.data();
        QString peer="[从 "+peerAddr.toString()+":"+QString::number(peerPort)+" 发送] ";

        ui->msgedit->append(peer+str);
        qDebug()<<peer+str;
    }
}
void Widget::broadcastSendData()
{
    m_socket->writeDatagram(ui->sendedit->text().toUtf8(),QHostAddress::Broadcast,ui->portedit->text().toInt());
}

void Widget::unicastOpen()
{
    if (m_socket->bind(QHostAddress::LocalHost,ui->portedit->text().toInt()))
    {
        QString msg = "打开单播";
        ui->msgedit->append(msg);
        m_joinFg = true;
        qDebug()<<msg;
    }
    else
    {
        ui->msgedit->append("打开单播失败");
        m_joinFg = false;
    }
}
void Widget::unicastClose()
{
    m_socket->abort();
    ui->msgedit->append("退出单播");
    ui->autoBox->setChecked(false);
    m_joinFg = false;
    m_timer.stop();
}
void Widget::unicastReadData()
{
    //读取数据
    while(m_socket->hasPendingDatagrams())//hasPendingDatagrams()如果至少有一个数据报等待读取,则返回true;
    {
        QByteArray datagram;
        datagram.resize(m_socket->pendingDatagramSize());
        QHostAddress peerAddr;
        quint16 peerPort;
        m_socket->readDatagram(datagram.data(),datagram.size(),&peerAddr,&peerPort);

        QString str=datagram.data();
        QString peer="[从 "+peerAddr.toString()+":"+QString::number(peerPort)+" 发送] ";

        ui->msgedit->append(peer+str);
        qDebug()<<peer+str;
    }
}
void Widget::unicastSendData()
{
    m_socket->writeDatagram(ui->sendedit->text().toUtf8(),QHostAddress::LocalHost,ui->portedit->text().toInt());
}

void Widget::on_autoBox_clicked(bool checked)
{
    if (checked)
        m_timer.start(200);
    else
        m_timer.stop();
}

void Widget::on_typebox_activated(int index)
{
    if (index == 1 || index == 2)
        ui->ipedit2->setEnabled(false);
}

源码

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

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

相关文章

CSS3中动画的使用animation

1.基本使用 2.其他属性 3.复合属性

前端实现json动画(附带示例)

前端实现json动画&#xff08;附带示例&#xff09; 使用lottie制作动画。1.json动画2.实现效果3.git仓库4.运行5.json动画天堂6.代码7. 经常使用的方法 使用lottie制作动画。 1.json动画 废话不多说&#xff0c;直接看效果图2.实现效果 3.git仓库 https://gitee.com/chaiach…

Ubuntu实现双击图标运行自己的应用软件

我们知道在Ubuntu上编写程序&#xff0c;最后编译得到的是一个可执行文件&#xff0c;大致如下 然后要运行的时候在终端里输入./hello即可 但是这样的话感觉很丑很不方便&#xff0c;下边描述一种可以类似Windows上那种双击运行的实现方式。 我们知道Ubuntu是有一些自带的程序…

【GPTs】Email Responder Pro:高效生成专业回复邮件

博客主页&#xff1a; [小ᶻZ࿆] 本文专栏: AIGC | GPTs应用实例 文章目录 &#x1f4af;GPTs指令&#x1f4af;前言&#x1f4af;Email Responder Pro主要功能适用场景优点缺点 &#x1f4af;小结 &#x1f4af;GPTs指令 Email Craft is a specialized assistant for cra…

阿里云ECS服务器使用限制及不允许做的事情

阿里云ECS&#xff08;Elastic Compute Service&#xff09;是一种高性能的弹性计算服务&#xff0c;允许用户在云端创建和管理虚拟服务器。尽管ECS提供了强大的功能&#xff0c;但在使用过程中&#xff0c;阿里云有一些限制和不允许的行为。以下是一些主要的使用限制和禁止行为…

《Atomic Picnic》进不去游戏解决方法

Atomic Picnic有时候会遇到进不去游戏的情况&#xff0c;这可能是由多种原因造成的&#xff0c;玩家可以采取很多解决方法&#xff0c;比如检查电脑配置、更新系统和驱动或验证游戏文件。 Atomic Picnic进不去游戏怎么办 检查电脑配置 查看自己的电脑配置是否达到了游戏的要求…

Fastify Swagger:自动化API文档生成与展示

在现代软件开发中&#xff0c;API文档的生成和维护是一个不可或缺的环节。Fastify Swagger 是一个专为 Fastify 框架设计的插件&#xff0c;它能够自动生成符合 Swagger&#xff08;OpenAPI v2 或 v3&#xff09;规范的文档&#xff0c;从而帮助开发者轻松创建和维护API文档。本…

Nuxt3之使用lighthouse性能测试及性能优化实操

lighthouse性能测试工具 什么是 LightHouse 呢 Lighthouse 是一个开源的自动化工具&#xff0c;用于提高网页的质量。可以通过浏览器的开发者工具运行&#xff0c;也可以作为命令行工具或 Node.js 模块集成到持续集成系统中。Lighthouse 可以帮助开发者&#xff1a; 性能优化…

基于单片机的自动充电蓝牙智能台灯的设计

本设计以单片机为主要控制芯片&#xff0c;主要包括主控模块&#xff0c;显示模块&#xff0c;蓝牙模块&#xff0c;ADC转换信号模块&#xff0c;红外感应模块&#xff0c;光敏模块&#xff0c;充电模块等多功能设计。台灯分为自动模式与手动模式&#xff0c;自动模式开启时&am…

Linux操作系统:学习进程_对进程概念的深入了解

目录 前言 开篇 一、进程概念 二、进程的描述与管理 1、如何描述与管理 2、Linux中的PCB-task_struct 3、对进程组织的理解 三、进程的属性 1、系统创建进程 2、查看进程 3、进程的标识符 4、退出进程 1>ctrlc 2>kill命令杀死进程 5、用户进程的创建方式…

PointMamba: A Simple State Space Model for Point Cloud Analysis——点云论文阅读(10)

此内容是论文总结&#xff0c;重点看思路&#xff01;&#xff01; 文章概述 这篇文章提出了PointMamba&#xff0c;一种基于状态空间模型&#xff08;SSM&#xff09;的点云分析方法&#xff0c;通过引入线性复杂度算法来实现高效的全局建模。与传统基于Transformer的点云方…

【LLM】【LLaMA-Factory】:Qwen2.5-Coder-7B能力测评

1 前期准备工作 1.1 环境概述 大模型框架&#xff1a;LLaMA-Factory CG客户端镜像&#xff1a;hiyouga/LLaMA-Factory/LLaMA-Factory / v4 cpu 架构 核心数 线程数 频率 内存使用情况 操作系统 GPU&#xff1a;四张4090显卡 CUDA python 以及相关依赖包 pytorch 1.2 数据准…

OpenAI CEO阿尔特曼预测AGI可能在五年内出现 对社会的影响远小于预期

OpenAI 不断探索人工智能及其所蕴含的技术可能性的工作已经引起了相当大的反响&#xff0c;用户和科技界都对其新发布的模型及其所蕴含的先进性着迷。 在公司大力发展 AGI&#xff08;人工通用智能&#xff09;的同时&#xff0c;许多知名公司的关键员工也加入了 OpenAI&#x…

AI周报(11.3-11.9)

AI应用--商务会议旅游必备 AI同传翻译耳机 作为一个经常出差和旅游的人&#xff0c;我深知语言不通带来的困扰。每次在国外旅行&#xff0c;面对不同语言的环境&#xff0c;总是让人头疼不已。幸好&#xff0c;现在有了AI同传翻译耳机&#xff0c;出门在外也能轻松交流。 时空…

qt QCompleter详解

1、概述 QCompleter是Qt框架中的一个类&#xff0c;用于为文本输入提供自动完成功能。它可以与Qt的输入控件&#xff08;如QLineEdit、QTextEdit等&#xff09;结合使用&#xff0c;根据用户的输入实时过滤数据源&#xff0c;并在输入控件下方或内部显示补全建议列表。用户可以…

为什么分布式光伏规模是6MW为界点

安科瑞 华楠 近日&#xff0c;能源局发布定义分布式光伏6MW及以上的光伏电站必须自发自用&#xff0c;自行消纳。多省能源局规定大于6MW的电站必须按集中式管理&#xff0c;另外大于6MW&#xff08;包含&#xff09;要省级审批&#xff0c;小于则由市级审批&#xff0c;10kV线…

【青牛科技】GC8549替代LV8549/ONSEMI在摇头机、舞台灯、打印机和白色家电等产品上的应用分析

引言 在现代电子产品中&#xff0c;控制芯片的性能直接影响到设备的功能和用户体验。摇头机、舞台灯、打印机和白色家电等领域对控制精度、功耗和成本等方面的要求日益提高。LV8549/ONSEMI等国际品牌的芯片曾是这些产品的主要选择&#xff0c;但随着国内半导体技术的进步&…

分析报告、调研报告、工作方案等的提示词

什么是提示词&#xff1f; 提示词的英文是Prompt&#xff0c;是你与人工智能&#xff08;AI&#xff09;进行交流的方式。简单来说&#xff0c;提示词就是你给AI的一段文字或问题&#xff0c;AI根据这段文字或问题来生成回应或完成任务。 举个例子&#xff1a;假设你在使用一…

Embedding 技术在推荐系统中的应用

参考自《深度学习推荐系统》——王喆&#xff0c;用于学习和记录。 介绍 Embedding&#xff0c;中文直译为“嵌入”&#xff0c;常被翻译为“向量化”或者“向量映射”。它的主要作用是将稀疏向量转换成稠密向量&#xff0c;便于上层深度神经网络处理。事实上&#xff0c;Emb…

解决Postman一直在转圈加载无法打开问题的方法

在使用Postman这款强大的API测试工具时&#xff0c;有时可能会遇到程序长时间加载而无法正常使用的情况。面对这样的问题&#xff0c;可以尝试以下几种解决办法&#xff1a; 方法一&#xff1a;直接运行Postman可执行文件 定位到Postman的安装目录 如果您不确定Postman的具体安…