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

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_OBJECTpublic: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);elsem_timer.stop();
}void Widget::on_typebox_activated(int index)
{if (index == 1 || index == 2)ui->ipedit2->setEnabled(false);
}

源码

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

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

相关文章

算法每日双题精讲——双指针(快乐数,盛最多水的容器)

&#x1f31f;快来参与讨论&#x1f4ac;&#xff0c;点赞&#x1f44d;、收藏⭐、分享&#x1f4e4;&#xff0c;共创活力社区。 &#x1f31f; 别再犹豫了&#xff01;快来订阅我们的算法每日双题精讲专栏&#xff0c;一起踏上算法学习的精彩之旅吧&#xff01;&#x1f4aa;…

C语言 | Leetcode C语言题解之第551题学生出勤记录I

题目&#xff1a; 题解&#xff1a; bool checkRecord(char* s) {int absents 0, lates 0;int n strlen(s);for (int i 0; i < n; i) {char c s[i];if (c A) {absents;if (absents > 2) {return false;}}if (c L) {lates;if (lates > 3) {return false;}} els…

【未解决】vite反向代理问题

文章目录 可行网页直接访问&#xff0c;数据正常返回不使用反向代理&#xff0c;直接用axios可以得到数据postman测试也正常 不行-vite反向代理出问题case1命令行测试 可行 网页直接访问&#xff0c;数据正常返回 在地址栏输入 https://api.binance.com/api/v3/ticker/price?…

github使用基础

要通过终端绑定GitHub账号并进行文件传输&#xff0c;你需要使用Git和SSH密钥来实现安全连接和操作。以下是一个基本流程&#xff1a; 设置GitHub和SSH 检查Git安装 通过终端输入以下命令查看是否安装Git&#xff1a; bash 复制代码 git --version配置Git用户名和邮箱 bash …

9_api_intro_imagerecognition_ocr2word

通用图片 OCR 到 Word API 数据接口 高可用图像识别引擎&#xff0c;基于机器学习&#xff0c;超精准识别率。 1. 产品功能 通用的识别接口&#xff0c; 支持多种图片格式&#xff1b;支持中英文字符混合识别&#xff1b;支持 Base64 以及网络地址传参&#xff1b;基于机器学习…

深度优先搜索之全排列问题(C语言版)

本文的一些参考&#xff1a; DFS (深度优先搜索) 算法详解 模板 例题&#xff0c;这一篇就够了_dfs算法-CSDN博客 首先把深度优先搜索算法的基本概论摆出来 深度优先搜索算法&#xff08;Depth First Search&#xff0c;简称DFS&#xff09;&#xff1a; 一种用于遍历或搜…

如何防止苹果MacOS进入休眠状态

前言 远程控制的时候&#xff0c;发现MacOS已经进入了休眠状态。如何设置MacOS&#xff0c;防止其进入休眠状态&#xff0c;这样才能远程控制。 1、进入系统偏好设置 显示器自动关闭了不要紧。只要操作系统不进入休眠就可以。

云计算:定义、类型及对企业的影响

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 云计算&#xff1a;定义、类型及对企业的影响 云计算&#xff1a;定义、类型及对企业的影响 云计算&#xff1a;定义、类型及对企…

Pr 视频过渡:沉浸式视频

效果面板/视频过渡/沉浸式视频 Video Transitions/Immersive Video Adobe Premiere Pro 的视频过渡效果中&#xff0c;沉浸式视频 Immersive Video效果组主要用于 VR 视频剪辑之间的过渡。 自动 VR 属性 Auto VR Properties是所有 VR 视频过渡效果的通用选项。 默认勾选&#x…

ArcGIS Pro SDK Addin-DAML

ArcGIS Pro SDK Addin-DAML 文章目录 ArcGIS Pro SDK Addin-DAML1 Panes: 重置窗格2 Button: 从功能区中移除核心按钮3 Button: 将新按钮插入功能区上的现有组4 Menu: 在图层上下文菜单中插入一个新按钮5 Menu: 在 Map Container 上下文菜单中插入新菜单6 Menu: 在2D Map上下文…

【电机控制器】STC8H1K芯片——ADC电压采集

【电机控制器】STC8H1K芯片——ADC电压采集 文章目录 [TOC](文章目录) 前言一、ADC1.ADC初始化1.ADC_CONTR2.ADCCFG3.ADCTIM4.代码 2.ADC读取1.ADC_RES、ADC_RESL2.代码 3.VREF电压读取——MCU工作电压1.MCU工作电压计算公式2.代码 4.ADC被转换通道的输入电压读取1.ADC被转换通…

SpringBoot基础系列学习(三):日志

文章目录 一丶日志控制台介绍二丶日志的用法三丶日志级别四丶配置文件参数及介绍五丶slf4j 一丶日志控制台介绍 只要引用了spring-boot-starter依赖,就无需引入日志依赖,里面自带了logging依赖,默认情况下,springBoot使用Logback来记录日志,并用INFO级别输出到控制台 二丶日…

鸿蒙系统:安卓与iOS的强劲对手

随着科技的迅猛发展&#xff0c;“纯血鸿蒙”系统HarmonyOS Next 5.0系统的推出引起了业界的广泛关注。用户们对这一新系统充满好奇&#xff0c;急切地想要体验其带来的变革。鸿蒙系统以其创新的设计和技术支持&#xff0c;成为与安卓和iOS并列的第三大操作系统。 鸿蒙系统的独…

Redis - 哨兵(Sentinel)

Redis 的主从复制模式下&#xff0c;⼀旦主节点由于故障不能提供服务&#xff0c;需要⼈⼯进⾏主从切换&#xff0c;同时⼤量 的客⼾端需要被通知切换到新的主节点上&#xff0c;对于上了⼀定规模的应⽤来说&#xff0c;这种⽅案是⽆法接受的&#xff0c; 于是Redis从2.8开始提…

Golang | Leetcode Golang题解之第552题学生出勤记录II

题目&#xff1a; 题解&#xff1a; const mod int 1e9 7type matrix [6][6]intfunc (a matrix) mul(b matrix) matrix {c : matrix{}for i, row : range a {for j : range b[0] {for k, v : range row {c[i][j] (c[i][j] v*b[k][j]) % mod}}}return c }func (a matrix) p…

放电电阻是什么

放电电阻&#xff0c;顾名思义&#xff0c;就是用于放电的电阻。在电路中&#xff0c;当电流突然增大时&#xff0c;如果没有适当的电阻来限制电流&#xff0c;就可能导致电路损坏。因此&#xff0c;放电电阻的作用就是在电路中起到限制电流的作用&#xff0c;防止电路因电流过…

CelebV-Text——从文本生成人脸视频的数据集

概述 近年来&#xff0c;生成模型在根据文本生成和编辑视频方面受到了广泛关注。然而&#xff0c;由于缺乏合适的数据集&#xff0c;生成人脸视频领域仍然是一个挑战。特别是&#xff0c;生成的视频帧质量较低&#xff0c;与输入文本的相关性较弱。在本文中&#xff0c;我们通…

【51单片机数码管的控制开机时前四位数码管显示0000,每按下一次按键后松开数字加121,当数字大于等于8888时清零。】2022-3-18

缘由51单片机数码管的控制-嵌入式-CSDN问答 #include "REG52.h" sbit K1 P3^1; unsigned char code SmZiFu[]{63,6,91,79,102,109,125,7,127,111,128,119,124,57,94,121,113};//0-9. void smxs(unsigned char mz, unsigned char w) {unsigned char Xd0;P2255;P2255…

境内部署DIfy(中篇)

背景&#xff1a; 接 本文上篇中已经讲述了比较友好的一种境内安装Dify 的方式&#xff0c;这种方式可以拉取到最新的镜像源&#xff0c;最新的版本&#xff0c;最为推荐的方案。但由于各种原因或多或少会出现上述方式不成功的可能&#xff08;镜像源又被屏蔽&#xff09;&…

【人工智能】利用大语言模型(LLM)实现机器学习模型选择与实验的自动化

文章目录 引言环境准备数据集说明 项目结构主要文件说明 导入必要的软件包软件包功能简述 辅助函数定义加载配置文件加载数据集预处理数据集函数功能详解 集成LLM进行模型选择调用LLM的函数定义函数功能详解 清理和验证LLM的输出清理超参数建议提取模型名称验证超参数修正超参数…