• Qt网络编程之搭建Udp通信【单播、组播、广播】


    由于项目的环境实在局域网内进行传输,所以采用了UDP通信。为此记录一下。

    UDP概念

    UDP(用户数据报协议)是一个简单的面向数据报的传输层协议。提供的是非面向连接的、不可靠的数据流传输。UDP不提供可靠性,也不提供报文到达确认、排序以及流量控制等功能。它只是把应用程序传给IP层的数据报发送出去,但是并不能保证它们能到达目的地。因此报文可能会丢失、重复以及乱序等。但由于UDP在传输数据报前不用在客户和服务器之间建立一个连接,且没有超时重发等机制,故而传输速度很快。

    UDP传输方式

    UDP有单播、广播、组播
    只有UDP有广播和多播, TCP只能进行点对点的单播, 多播的重点是高效的把同一个包尽可能多的发送到不同的,甚至可能是未知的设备。但是TCP连接是一对一明确的,只能单播。

    文中涉及到所有的代码下载地址

    代码下载。这里有文章中所有的代码。如果没有积分可以私聊我发你。

    单播

    服务端(发送者)

    服务器端不需要绑定。只需要在发送时指定对方IP以及端口即可。

    m_sender->writeDatagram(dataGram.data(),// 发送内容
                            dataGram.size(),// 发送长度
                            QHostAddress("192.168.0.108"),  // 对方IP
                            6666);//对方端口
    
    • 1
    • 2
    • 3
    • 4

    客户端(接收者)

    客户端需要提前将本地IP和对应的端口进行绑定。然后关联readyRead信号。进行对应的实时读取。
    下面这段代码是提前进行绑定和对应的信号槽关联

        groupAddress = QHostAddress("192.168.0.112");			// 本地地址
        int port1 = 6666;													// 本地端口
        bool ret = m_receiver->bind(groupAddress,port1,QUdpSocket::ShareAddress);
        if(ret == false)
        {
            QMessageBox::warning(this,"error", "绑定失败");
        }
        //当接收端接收到数据时,就会发送readRead信号
        connect(m_receiver,&QUdpSocket::readyRead,this,&ReceiverWidget::processData);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    下面这段代码是槽函数的一个实时读取并显示在标签上。

    void ReceiverWidget::processData()
    {
        QString strData;
        //有未处理的数据报
        while(m_receiver->hasPendingDatagrams())
        {
            QByteArray dataGram;
            //读取的数据报大小
            dataGram.resize(m_receiver->pendingDatagramSize());
            m_receiver->readDatagram(dataGram.data(),dataGram.size());
            ui->textBrowser->insertPlainText(dataGram);   //将接收到的数据显示到标签上
            ui->textBrowser->insertPlainText("\n");   //将接收到的数据显示到标签上
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    效果图

    在这里插入图片描述

    组播

    组播相当于是在广播的基础上在加入组播。

    服务端(发送者)

    服务器端不需要绑定。只需要在发送时指定对方IP以及端口即可。

        m_sender=new QUdpSocket(this);
        QByteArray dataGram= ui->lineEdit->text().toUtf8();
        QHostAddress appaddr;
        m_sender->writeDatagram(dataGram.data(),
                                dataGram.size(),
                                QHostAddress("224.0.0.0"),// 组播地址
                                7755);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    客户端(接收者)

    客户端需要对应的端口进行绑定。并加入到组播地址中,然后关联readyRead信号。进行对应的实时读取。
    下面这段代码是提前进行绑定、加入组并关联信号和槽

        groupAddress = QHostAddress("224.0.0.0");			// 组播地址
        port = 7755;
        m_receiver = new QUdpSocket(this);
        bool aa = m_receiver->bind(QHostAddress::AnyIPv4, port, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint);
        if(false == aa)
        {
            qDebug() << "绑定失败!";
        }
    
        // 加入组播
        bool cc = m_receiver->joinMulticastGroup(groupAddress);
        if(false == cc)
        {
            qDebug() << "加入组播失败!";
        }
        //当接收端接收到数据时,就会发送readRead信号
        connect(m_receiver, &QUdpSocket::readyRead, this, &ReceiverWidget::processData);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    下面这段代码是槽函数的一个实时读取并显示在标签上。

    void ReceiverWidget::processData()
    {
        QString strData;
        //有未处理的数据报
        while(m_receiver->hasPendingDatagrams())
        {
            QByteArray dataGram;
            //读取的数据报大小
            dataGram.resize(m_receiver->pendingDatagramSize());
            m_receiver->readDatagram(dataGram.data(),dataGram.size());
            ui->textBrowser->insertPlainText(dataGram);   //将接收到的数据显示到标签上
            ui->textBrowser->insertPlainText("\n");   //将接收到的数据显示到标签上
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    效果图

    在这里插入图片描述

    广播

    广播只需要绑定端口即可。

    服务器(发送者)

    不需要绑定。发送时仅确定端口即可。

    QByteArray dataGram= ui->lineEdit->text().toUtf8();
    m_sender->writeDatagram(dataGram.data(),
                                dataGram.size(),
                                QHostAddress::Broadcast,
                                7755);
    
    • 1
    • 2
    • 3
    • 4
    • 5

    客户端(接收者)

    需要绑定所有的Ip地址(AnyIPv4)以及对应的端口。然后关联readyRead信号。进行对应的实时读取。
    下面这段代码是提前进行绑定和对应的信号槽关联。
    下面这段代码是提前进行绑定和对应的信号槽关联

        port = 7755;
        m_receiver = new QUdpSocket(this);
        bool aa = m_receiver->bind(QHostAddress::AnyIPv4, port, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint);
        if(false == aa)
        {
            qDebug() << "绑定失败!";
        }
        //当接收端接收到数据时,就会发送readRead信号
        connect(m_receiver, &QUdpSocket::readyRead, this, &ReceiverWidget::processData);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    下面这段代码是槽函数的一个实时读取并显示在标签上。

    void ReceiverWidget::processData()
    {
        QString strData;
        //有未处理的数据报
        while(m_receiver->hasPendingDatagrams())
        {
            QByteArray dataGram;
            //读取的数据报大小
            dataGram.resize(m_receiver->pendingDatagramSize());
            m_receiver->readDatagram(dataGram.data(),dataGram.size());
            ui->textBrowser->insertPlainText(dataGram);   //将接收到的数据显示到标签上
            ui->textBrowser->insertPlainText("\n");   //将接收到的数据显示到标签上
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    效果图

    在这里插入图片描述

  • 相关阅读:
    Hadoop版本演变、分布式集群搭建
    EventBus 一篇文章就够了
    cwnd < 1 时的拥塞控制
    数据结构-堆基本应用刷题
    C++ 类的声明笔记
    Python文件操作
    使用open webui+ollama部署本地大模型
    搞定面试官 - 你可以介绍一下在 MySQL 中,哪些情况下 索引会失效嘛?
    通信协议(三)——IIC协议
    LeetCode - 搜索二维矩阵
  • 原文地址:https://blog.csdn.net/qq_45254369/article/details/125417908