更多精彩内容 |
---|
个人内容分类汇总 |
简易版 |
---|
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) |
使用QUdpSocket实现UDP组播通信功能,十分简易的入门Demo |
第一,绝对不意气用事;
第二,绝对不放过任何一个注释;
第三,绝对保证代码的简洁明了。
为了便于学习,在这个Demo里会尽可能简单的实现UDP组播通信功能,尽可能少的引入其它功能,只保留了基本功能,所以可能会有一些bug。
实现功能:
- 在同一系统下,同一时间可打开多个UDP组播窗口,绑定同一个端口号进行通信;
- 数据接收功能;
- 数据发送功能。
组播需要使用组播地址,在 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: 为本地管理组播地址,仅在特定的本地范围内有效;
提高效率: 降低网络流量、减轻硬件负荷;
优化性能: 减少冗余流量、节省网络带宽、降低网络负载;
分布式应用: 是多点应用成为可能;
组播非常适合一对多的通信模型,只有加入到特定组播组的成员,才会受到组播数据,当存在多个组播组成员时,源无需拷贝多个数据发送,仅需发送一份即可,组播网络设备(运行组播路由协议的网络设备)会根据实际需要转发或拷贝组播数据,实现按需拷贝,按需发送;
数据流只发送给加入该组播组的接收者(组成员),而不需要该数据的设备将不会接收到该组播流量;
相同的组播报文,在一段链路上仅有一份数据,大大提高了网络资源的利用率。
信号 | 说明 |
---|---|
readyRead | 有可读数据时发出此信号 |
函数名 | 说明 |
---|---|
state | 判断QUdpSocket当前状态,BoundState已绑定本地端口 |
bind | 绑定本地IP、端口,需要指定AnyIPv4 |
joinMulticastGroup | 加入组播组 |
writeDatagram | 发送数据报 |
receiveDatagram | 读取数据报 |
leaveMulticastGroup | 离开组播组 |
abort | 关闭套接字连接(解除绑定的端口号) |
.pro
文件里添加QT += network
,否则编译失败。/******************************************************************************
* @文件名 simpleudpgroup.h
* @功能 简易的UDP组播通信Demo,主要:UDP组播不能使用connectToHost绑定地址
*
* @开发者 mhf
* @邮箱 [email protected]
* @时间 2022/04/19
* @备注
*****************************************************************************/
#ifndef SIMPLEUDPGROUP_H
#define SIMPLEUDPGROUP_H
#include
#include
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
#include "simpleudpgroup.h"
#include "ui_simpleudpgroup.h"
#include
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);
}
gitee
github