Qt网络编程-简易版UDP组播通信入门Demo(5)🍳
文章目录
更多精彩内容 |
---|
👉个人内容分类汇总 👈 |
简易版 |
---|
👉Qt网络编程-简易版TcpClient入门Demo(1)👈 |
👉Qt网络编程-简易版TcpServer入门Demo(2)👈 |
👉Qt网络编程-简易版UDP单播通信入门Demo(3)👈 |
👉Qt网络编程-简易版UDP单播通信入门Demo(4)👈 |
👉Qt网络编程-简易版UDP组播通信入门Demo(5)👈 |
👉Qt网络编程-简易版UDP广播通信入门Demo(6)👈 |
进阶版 |
---|
👉Qt网络编程-TcpClient入门Demo(1)👈 |
👉Qt网络编程-TcpServer入门Demo(2)👈 |
1、概述🥚
使用QUdpSocket实现UDP组播通信功能,十分简易的入门Demo |
第一,绝对不意气用事;
第二,绝对不放过任何一个注释;
第三,绝对保证代码的简洁明了。🤘
为了便于学习,在这个Demo里会尽可能简单的实现UDP组播通信功能,尽可能少的引入其它功能,只保留了基本功能,所以可能会有一些bug。
实现功能:
- 在同一系统下,同一时间可打开多个UDP组播窗口,绑定同一个端口号进行通信;
- 数据接收功能;
- 数据发送功能。
2、组播🍚
2.1 什么是组播🍪
- 组播也可以称之为多播,是 UDP 的特性之一。
- 组播是主机间一对多的通讯模式,是一种允许一个或多个组播源发送同一报文到多个接收者的技术。
- 组播源将一份报文发送到特定的组播地址,组播地址不同于单播地址,它并不属于特定某个主机,而是属于一组主机。一个组播地址表示一个群组,需要接收组播报文的接收者都加入这个群组。
- 广播只能在局域网访问内使用,组播既可以在局域网中使用,也可以用于广域网;
- 在发送广播消息的时候,连接到局域网的客户端不管想不想都会接收到广播数据,组播可以控制发送端的消息能够被哪些接收端接收,更灵活和人性化。
- UDP组播是采用的无连接,数据报的连接方式,所以是不可靠的。也就是数据能不能到达接受端和数据到达的顺序都是不能保证的。但是由于UDP不用保证数据 的可靠性,所有数据的传送效率是很快的。
2.2 组播地址🍰
-
组播需要使用组播地址,在 IPv4 中它的范围从 224.0.0.0 到 239.255.255.255,并被划分为局部链接多播地址、预留多播地址和管理权限多播地址三类
224.0.0.0 ~ 224.0.0.255: 局部链接多播地址:是为路由协议和其它用途保留的地址,只能用于局域网中,路由器是不会转发的地址 224.0.0.0 不能用,是保留地址;
224.0.1.0 ~ 224.0.1.255: 为用户可用的组播地址(临时组地址),可以用于 Internet 上的;
224.0.2.0 ~ 238.255.255.255: 用户可用的组播地址(临时组地址),全网范围内有效;
239.0.0.0 ~ 239.255.255.255: 为本地管理组播地址,仅在特定的本地范围内有效;
2.3 组播优点🧁
-
提高效率: 降低网络流量、减轻硬件负荷;
-
优化性能: 减少冗余流量、节省网络带宽、降低网络负载;
-
分布式应用: 是多点应用成为可能;
-
组播非常适合一对多的通信模型,只有加入到特定组播组的成员,才会受到组播数据,当存在多个组播组成员时,源无需拷贝多个数据发送,仅需发送一份即可,组播网络设备(运行组播路由协议的网络设备)会根据实际需要转发或拷贝组播数据,实现按需拷贝,按需发送;
-
数据流只发送给加入该组播组的接收者(组成员),而不需要该数据的设备将不会接收到该组播流量;
-
相同的组播报文,在一段链路上仅有一份数据,大大提高了网络资源的利用率。
2.4 组播缺点🥧
- 组播是基于UDP的,采用尽力而为的传输方式;
- 没有拥塞避免机制;
- 可能出现报文重复的现象;
- 可能出现报文失序的现象。
2.5 组播使用场景🍫
- 组播使用于多接受者期望接受相同流量的场景(聊天群,屏幕共享);
- 多媒体直播;
- 培训、联合作业场景的通信;
- 数据仓库、金融应用(股票);
- 其他“单到多”数据发布应用。
3、UDP组播通信流程图🥦
- UDP不同于TCP,不需要区分Server和Cilent,数据发送端和接收端都一样;
4、 关键信号🌮
信号 | 说明 |
---|---|
readyRead | 有可读数据时发出此信号 |
5、 关键函数 🍤
函数名 | 说明 |
---|---|
state | 判断QUdpSocket当前状态,BoundState已绑定本地端口 |
bind | 绑定本地IP、端口,需要指定AnyIPv4 |
joinMulticastGroup | 加入组播组 |
writeDatagram | 发送数据报 |
receiveDatagram | 读取数据报 |
leaveMulticastGroup | 离开组播组 |
abort | 关闭套接字连接(解除绑定的端口号) |
6、主要代码🍧
- 注意:在
.pro
文件里添加QT += network
,否则编译失败。 - .h文件
/******************************************************************************
* @文件名 simpleudpgroup.h
* @功能 简易的UDP组播通信Demo,主要:UDP组播不能使用connectToHost绑定地址
*
* @开发者 mhf
* @邮箱 1603291350@qq.com
* @时间 2022/04/19
* @备注
*****************************************************************************/
#ifndef SIMPLEUDPGROUP_H
#define SIMPLEUDPGROUP_H
#include <QWidget>
#include <QUdpSocket>
namespace Ui {
class SimpleUdpGroup;
}
class SimpleUdpGroup : public QWidget
{
Q_OBJECT
public:
explicit SimpleUdpGroup(QWidget *parent = nullptr);
~SimpleUdpGroup();
private slots:
void on_readyRead();
void on_but_connect_clicked();
void on_but_send_clicked();
private:
Ui::SimpleUdpGroup *ui;
QUdpSocket* m_udpSocket = nullptr; // UDP通信对象
};
#endif // SIMPLEUDPGROUP_H
- .cpp文件
#include "simpleudpgroup.h"
#include "ui_simpleudpgroup.h"
#include <qnetworkdatagram.h>
SimpleUdpGroup::SimpleUdpGroup(QWidget *parent) :
QWidget(parent),
ui(new Ui::SimpleUdpGroup)
{
ui->setupUi(this);
this->setWindowTitle("简易版UDP组播通信Demo");
m_udpSocket = new QUdpSocket(this);
connect(m_udpSocket, &QUdpSocket::readyRead, this, &SimpleUdpGroup::on_readyRead); // 当有可读数据时发出readyRead信号
}
SimpleUdpGroup::~SimpleUdpGroup()
{
delete ui;
}
/**
* @brief 读取UDP数据报
*/
void SimpleUdpGroup::on_readyRead()
{
QNetworkDatagram datagram = m_udpSocket->receiveDatagram(); // 读取数据,这里需要添加qnetworkdatagram.h头文件
ui->text_recv->append(datagram.data()); // 显示读取到的数据
}
/**
* @brief 开始绑定绑定IP端口,用于接收数据,并加入组播组
*/
void SimpleUdpGroup::on_but_connect_clicked()
{
if(m_udpSocket->state() != QAbstractSocket::BoundState) // 判断是否绑定绑定端口
{
bool ret = m_udpSocket->bind(QHostAddress::AnyIPv4, // 使用组播时这里必须要指定AnyIPv4,不指定将会默认Any,加入组播会失败
ui->spin_groupPort->value(), // 绑定绑定接收数据的端口,一般用组播端口
QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint); // ShareAddress允许一台电脑上多个程序绑定同一个端口,便于测试,但是在windows下需要加上ReuseAddressHint才有效
if(ret)
{
qInfo() << "绑定本地地址成功!";
ret = m_udpSocket->joinMulticastGroup(QHostAddress(ui->line_groupAddress->text())); // 加入组播组
if(ret)
{
qInfo() << "加入组播组成功!";
ui->but_connect->setText("关闭");
}
else
{
qWarning() << "加入组播组失败!";
}
}
else
{
qWarning() << "绑定本地地址失败!";
}
}
else
{
bool ret = m_udpSocket->leaveMulticastGroup(QHostAddress(ui->line_groupAddress->text()));
if(ret)
{
qInfo() << "移除组播组成功!";
m_udpSocket->abort();
ui->but_connect->setText("打开");
}
else
{
qWarning() << "移除组播组失败!";
}
}
}
/**
* @brief 发送数据,由于已经绑定了目标IP和目标端口号,在发送数据时就不用指定IP、端口了
*/
void SimpleUdpGroup::on_but_send_clicked()
{
QString str = ui->text_send->toPlainText();
qint64 len = m_udpSocket->writeDatagram(str.toUtf8(), QHostAddress(ui->line_groupAddress->text()), ui->spin_groupPort->value());
qInfo() << QString("发送数据长度:%1").arg(len);
}
7、实现效果🥠
8、源代码🥮
🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘