《QT6/C++开发指南》网络/UDP通信/组播/案例15-4

效果图

没有两个计算机,暂时没有效果图

界面设计

在这里插入图片描述

代码

.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include    <QMainWindow>

#include    <QUdpSocket>
#include    <QLabel>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

private:
    QLabel  *labSocketState;
    QUdpSocket  *udpSocket;         //socket连接
    QHostAddress    groupAddress;   //组播地址(占内存小,没必要用指针)
    QString getLocalIP();           //获取本机IP地址
public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    //自定义槽函数
    void    do_socketStateChange(QAbstractSocket::SocketState socketState);
    void    do_socketReadyRead();//读取socket传入的数据
    //
    void on_actStart_triggered();

    void on_actStop_triggered();

    void on_actClear_triggered();

    void on_actHostInfo_triggered();

    void on_btnMulticast_clicked();

private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

.cpp

在这里插入图片描述

在这里插入图片描述

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include    <QtNetwork>

QString MainWindow::getLocalIP()
{
    QString hostName=QHostInfo::localHostName();//本地主机名
    QHostInfo   hostInfo=QHostInfo::fromName(hostName);
    QString   localIP="";
    QList<QHostAddress> addList=hostInfo.addresses();
    if (addList.isEmpty())
        return localIP;

    foreach (QHostAddress aHost,addList)
        if (QAbstractSocket::IPv4Protocol==aHost.protocol())
        {
            localIP=aHost.toString();
            break;
        }
    return localIP;
}

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    // 1、状态栏
    labSocketState=new QLabel("Socket状态:");
    labSocketState->setMinimumWidth(300);
    ui->statusBar->addWidget(labSocketState);
    // 2、窗口标题
    QString localIP=getLocalIP();   //本地主机名
    this->setWindowTitle(this->windowTitle()+"----本机IP地址:"+localIP);
    // 3、udpSocket
    udpSocket=new QUdpSocket(this); // 创建对象
    //Multicast路由层次,1表示只在同一局域网内
    //组播TTL: 生存时间,每跨1个路由会减1,多播无法跨过大多数路由所以为1
    //默认值是1,表示数据包只能在本地的子网中传送。
    udpSocket->setSocketOption(QAbstractSocket::MulticastTtlOption,1); // 对udpSocket进行一些设置(设置什么,设置的值)
    //    udpSocket->setSocketOption(QAbstractSocket::MulticastTtlOption,ui->spinTTL->value());

    connect(udpSocket,&QUdpSocket::stateChanged,this,&MainWindow::do_socketStateChange); // 1、状态变化的时候
    do_socketStateChange(udpSocket->state());   //立即刷新一次

    connect(udpSocket,SIGNAL(readyRead()),this,SLOT(do_socketReadyRead())); // 2、有数据可以读的时候
}

MainWindow::~MainWindow()
{
//    udpSocket->abort();
//    delete udpSocket; //没必要
    delete ui;
}

void MainWindow::do_socketStateChange(QAbstractSocket::SocketState socketState)
{
    switch(socketState)
    {
    case QAbstractSocket::UnconnectedState:
        labSocketState->setText("socket状态:UnconnectedState");
        break;
    case QAbstractSocket::HostLookupState:
        labSocketState->setText("socket状态:HostLookupState");
        break;
    case QAbstractSocket::ConnectingState:
        labSocketState->setText("socket状态:ConnectingState");
        break;
    case QAbstractSocket::ConnectedState:
        labSocketState->setText("socket状态:ConnectedState");
        break;
    case QAbstractSocket::BoundState:
        labSocketState->setText("socket状态:BoundState");
        break;
    case QAbstractSocket::ClosingState:
        labSocketState->setText("socket状态:ClosingState");
        break;
    case QAbstractSocket::ListeningState:
        labSocketState->setText("socket状态:ListeningState");
    }
}

void MainWindow::do_socketReadyRead()
{//读取数据报
    while(udpSocket->hasPendingDatagrams())
    {
        QByteArray   datagram;
        datagram.resize(udpSocket->pendingDatagramSize());
        QHostAddress    peerAddr;
        quint16 peerPort;
        udpSocket->readDatagram(datagram.data(),datagram.size(),&peerAddr,&peerPort);
        //        udpSocket->readDatagram(datagram.data(),datagram.size());
        QString str=datagram.data();

        QString peer="[From "+peerAddr.toString()+":"+QString::number(peerPort)+"] ";
        ui->textEdit->appendPlainText(peer+str);
    }
}

void MainWindow::on_actStart_triggered()
{//"加入组播"按钮
    QString   IP=ui->comboIP->currentText();
    groupAddress=QHostAddress(IP);      //多播组地址
    quint16   groupPort=ui->spinPort->value();    //端口
    if (udpSocket->bind(QHostAddress::AnyIPv4, groupPort, QUdpSocket::ShareAddress))
    {
        udpSocket->joinMulticastGroup(groupAddress); //加入多播组
        ui->textEdit->appendPlainText("**加入组播成功");
        ui->textEdit->appendPlainText("**组播地址IP:"+IP);
        ui->textEdit->appendPlainText("**绑定端口:"+QString::number(groupPort));
        ui->actStart->setEnabled(false);
        ui->actStop->setEnabled(true);
        ui->comboIP->setEnabled(false);
        ui->spinPort->setEnabled(false);
        ui->btnMulticast->setEnabled(true);
    }
    else
        ui->textEdit->appendPlainText("**绑定端口失败");
}

void MainWindow::on_actStop_triggered()
{//"退出组播"按钮
    udpSocket->leaveMulticastGroup(groupAddress);   //退出组播
    udpSocket->abort();     //解除绑定
    ui->actStart->setEnabled(true);
    ui->actStop->setEnabled(false);
    ui->comboIP->setEnabled(true);
    ui->spinPort->setEnabled(true);
    ui->btnMulticast->setEnabled(false);
    ui->textEdit->appendPlainText("**已退出组播,解除端口绑定");
}

void MainWindow::on_actClear_triggered()
{
    ui->textEdit->clear();
}

void MainWindow::on_actHostInfo_triggered()
{
    QString  hostName=QHostInfo::localHostName();//本地主机名
    ui->textEdit->appendPlainText("本机主机名:"+hostName+"\n");
    QHostInfo  hostInfo=QHostInfo::fromName(hostName);
    QList<QHostAddress> addList=hostInfo.addresses();
    if (addList.isEmpty())
        return;

    foreach (QHostAddress aHost, addList)
        if (QAbstractSocket::IPv4Protocol==aHost.protocol())
        {
            QString IP=aHost.toString();
            ui->textEdit->appendPlainText("本机IP地址:"+aHost.toString());
            if (ui->comboIP->findText(IP)<0)
                ui->comboIP->addItem(IP);
        }
}


void MainWindow::on_btnMulticast_clicked()
{//"组播消息"按钮, 发送组播消息
    quint16  groupPort=ui->spinPort->value();  //组播端口
    QString  msg=ui->editMsg->text();
    QByteArray  datagram=msg.toUtf8();

    udpSocket->writeDatagram(datagram, groupAddress, groupPort);
    ui->textEdit->appendPlainText("[multicast] "+msg);
    ui->editMsg->clear();
    ui->editMsg->setFocus();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值