Qt 实例19 UDP组播

本文介绍了UDP组播的概念,包括其一对一组的通信模式、组播地址的范围以及永久和临时组播地址的区别。文章提供了一段使用Qt库实现的UDP组播功能的C++代码,展示了如何加入和离开组播组,以及发送和接收数据报的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

组播是主机之间“一对一组”的通信模式,当多个客户端加入由一个组播地址定义的多播组之后,客户端向组播地址和端口发送数据报,组内成员都可以接收到,类似QQ群。

UDP组播必须使用一个组播地址。组播地址是D类IP地址,有特定的地址段。多播组可以是永久的也可以是临时的。永久多播组保持不变的是它的IP地址,组内成员结构可以发生变化。

  • 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为本地管理组播地址,仅在特定的本地范围内有效

  • 若在家庭或办公室局域网内测试UDP组播功能,可以使用组播地址范围是239.0.0.0~239.255.255.255

joinMulticastGroup()函数使主机加入一个多播组,leaveMulticastGroup()函数使主机离开一个多播组。

UDP组播的特点是使用组播地址,其他的端口绑定、数据报收发功能与单播UDP完全相同。

6bf2ffc4af948dc636f3a8b552a2f9b3.png

实现代码如下:

#ifndef WIDGET_H
#define WIDGET_H
 
#include <QWidget>
#include <QUdpSocket>
 
namespace Ui {
class Widget;
}
 
class Widget : public QWidget
{
    Q_OBJECT
 
public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();
 
private slots:
    void on_btnClear_clicked();
 
    void on_btnSend_clicked();
 
    void on_readyRead();
    void on_btnJoin_clicked();
 
    void on_btnExit_clicked();
 
private:
    Ui::Widget *ui;
 
private:
    QUdpSocket *m_udpSocket = nullptr;
 
    QHostAddress groupAddr; //组播地址
};
 
#endif // WIDGET_H
#include "widget.h"
#include "ui_widget.h"
#include <QHostInfo>
 
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
 
    //本地主机名
    QString hostName = QHostInfo::localHostName();
 
    m_udpSocket = new QUdpSocket(this);
 
    //socket QAbstractSocket::MulticastTtlOption值为1,MulticastTtlOption是
    //组播的数据的生存期,数据报没跨1个路由就会减1.表示多播数据报只能在同一路由下的局域网内传播
    m_udpSocket->setSocketOption(QAbstractSocket::MulticastTtlOption,1);
    connect(m_udpSocket,&QUdpSocket::readyRead,this,&Widget::on_readyRead);
 
}
 
Widget::~Widget()
{
    delete ui;
}
 
 
void Widget::on_btnClear_clicked()
{
    ui->plainTextEdit->clear();
}
 
void Widget::on_btnSend_clicked()//组播
{
    //目标端口
    quint16 groupPort = ui->spinBindPort->value();
 
    QString msg = ui->lineEdit->text();
    QByteArray str = msg.toUtf8();
 
    //发出数据报
    m_udpSocket->writeDatagram(str,groupAddr,groupPort);
 
    ui->plainTextEdit->appendPlainText("[multicast] "+msg);
}
 
void Widget::on_readyRead()
{
    while(m_udpSocket->hasPendingDatagrams())
    {
        QByteArray data;
        data.resize(m_udpSocket->pendingDatagramSize());
 
        QHostAddress peerAddr;
 
        quint16 peerPort;
 
        m_udpSocket->readDatagram(data.data(),data.size(),&peerAddr,&peerPort);
 
        QString str = data.data();
 
        QString peer = "[From ] +"+peerAddr.toString()+":"+QString::number(peerPort)+"] ";
 
        ui->plainTextEdit->appendPlainText(peer+str);
    }
}
 
void Widget::on_btnJoin_clicked()
{
    QString IP = ui->comboBox->currentText();
    groupAddr = QHostAddress(IP);
 
    quint16 groupPort = ui->spinBindPort->value();
    //加入组播之前,必须先绑定端口,端口为多播组统一的一个端口。
    if(m_udpSocket->bind(QHostAddress::AnyIPv4,groupPort,QUdpSocket::ShareAddress))
    {
        //加入组播
        m_udpSocket->joinMulticastGroup(groupAddr);
 
        ui->plainTextEdit->appendPlainText("**加入组播成功");
        ui->plainTextEdit->appendPlainText("**组播IP: "+ IP);
        ui->plainTextEdit->appendPlainText("**绑定端口: "+QString::number(groupPort));
        ui->btnJoin->setEnabled(false);
        ui->btnExit->setEnabled(true);
        ui->comboBox->setEnabled(false);
    }
    else
    {
        ui->plainTextEdit->appendPlainText("**绑定端口失败");
    }
}
 
void Widget::on_btnExit_clicked()
{
    //退出组播
    m_udpSocket->leaveMulticastGroup(groupAddr);
 
    //解除绑定
    m_udpSocket->abort();
 
    ui->btnJoin->setEnabled(true);
 
    ui->btnExit->setEnabled(false);
    ui->comboBox->setEnabled(true);
 
    ui->plainTextEdit->appendPlainText("**已退出组播");
}

原文链接:https://blog.youkuaiyun.com/wzz953200463/article/details/115101133

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值