QT使用多线程的方式实现UDP的接收

使用多线程的方式,实现UDP数据的接收,并将接收到的UDP数据打印到textEdit当中。

今天这个demo主要是使用socket绑定一个固定的IP个端口接收UDP数据,使用moveToThread的方式将UDP的接收放到子线程里面。

废话不多说,直接开始:

步骤1:界面设计,这里其实只需要绑定自己的IP和接收端口就好了,我主要是想要后面接着利用这个demo写其他的东西,所以就多添加了写组件,注意要添加一个textEdit来显示接收到的数据。

步骤二:创建一个ReceiveClass.cpp和ReceiveClass.h来实现咱们的UDP接收class:

ReceiveClass.h

#ifndef RECEIVECLASS_H
#define RECEIVECLASS_H
#include <QObject>
#include <QUdpSocket>


class ReceiveClass : public QObject
{
    Q_OBJECT
public:
    explicit ReceiveClass(QObject *parent = nullptr) : QObject(parent) {}

    void ReceiveSocketInif(QString ip,quint16 port);

    //定义槽函数
public slots:
    void startReceiving();

    //定义信号
signals:
    //UDP接收到数据信号
    void datagramReceived(QByteArray data);
    //日志输出信号
     void UdpRcvLogSingal(const QString& text);

    //定义槽处理函数
private slots:
    void processPendingDatagrams();

private:
    QUdpSocket *socket;
};

#endif // RECEIVECLASS_H

ReceiveClass.cpp

#include "ReceiveClass.h"
bool socketInitFlag = false;


void ReceiveClass::ReceiveSocketInif(QString ip,quint16 port)
{
    QString log = "";
    bool ret = false;
    // 创建QUdpSocket对象
    socket = new QUdpSocket(this);
    QHostAddress IP(ip);
    ret = socket->bind(IP, port);
    if(ret == true)
    {
        socketInitFlag = true;
        log += "Socket初始化成功\n";
    }
    else
    {
        socketInitFlag = false;
        log += "Socket初始化失败\n";
    }
    emit UdpRcvLogSingal(log);
}

void ReceiveClass::startReceiving()
{
    QString log = "";
    //当前socket已经初始化完成
    if((socketInitFlag == true) && (nullptr != socket ))
    {
        connect(socket, &QUdpSocket::readyRead, this, &ReceiveClass::processPendingDatagrams);
    }
    else
    {
        log += "接收socket未初始化未完成\n";
    }
    emit UdpRcvLogSingal(log);
}

//收到数据后完成数据读取连接信号
void ReceiveClass::processPendingDatagrams()
{
    while (socket->hasPendingDatagrams())
            {
                QByteArray datagram;
                datagram.resize(socket->pendingDatagramSize());
                //将信息读取完成
                socket->readDatagram(datagram.data(), datagram.size());
                //传递信号
                emit datagramReceived(datagram);
            }
}


步骤3:在自己的主窗口文件中实现几个槽函数,日志输出槽函数和UDP接收处理槽函数

函数实现

//接收数据槽处理函数
void MainWindow::handleReceivedDatagram(QByteArray data)
{
    QString str = "";
    const uint8_t* receiveBuffer = reinterpret_cast<const uint8_t*>(data.constData());
    for(size_t i=0; i< data.size(); i++)
    {
        //将接收到的数据按照16进制的方式显示
        str += QString("%1").arg(static_cast<quint8>(receiveBuffer[i]), 2, 16, QLatin1Char('0'));
        str += " ";
    }
    //将接收到的数据打印
    MainWindow::LogPrint(str);
}

//日志输出
void MainWindow::LogPrint(const QString& text)
{
    ui->textEdit->append(text);
}

在绑定按钮的点击槽函数实现socket的初始化和线程处理

//绑定按钮点击
void MainWindow::on_pushButton_2_clicked()
{
    QString srcip = ui->lineEdit->text();
    quint16 srcRcvPort = ui->lineEdit_4->text().toInt();
    quint16 srcSedPort = ui->lineEdit_3->text().toInt();

    QString dstip = ui->lineEdit_2->text();
    quint16 dstRcvPort = ui->lineEdit_6->text().toInt();
    quint16 dstSedPort = ui->lineEdit_5->text().toInt();

    //绑定接收端口
    receiveClass->ReceiveSocketInif(srcip,srcRcvPort);

    //将uDPReceiver移动到udpReceiveThread线程中执行
    receiveClass->moveToThread(udpReceiveThread);

    //连接线程线程开始信号到UDP接收
    connect(udpReceiveThread, &QThread::started, receiveClass, &ReceiveClass::startReceiving);

    //收到数据后连接到数据处理槽函数
    connect(receiveClass, &ReceiveClass::datagramReceived, this, &MainWindow::handleReceivedDatagram);

    udpReceiveThread->start();

}

然后注意在绑定测试的时候,注意在自己电脑上需要添加自己的IP,不然绑定会失败。

测试效果:

  • 20
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
您好!对于在Qt C++中实现多线程接收UDP组播的问题,可以按照以下步骤进行操作: 1. 创建一个继承自QObject的自定义类,用于处理UDP组播的接收逻辑。例如,可以命名为UdpReceiver。 2. 在UdpReceiver类中,定义一个成员变量QUdpSocket,用于实现UDP套接字的创建和操作。 3. 在UdpReceiver类中创建一个公共函数,用于接收UDP组播数据。可以命名为receiveData()。 4. 在receiveData()函数中,使用QUdpSocket的bind()函数绑定到指定的组播地址和端口。例如: ```cpp udpSocket->bind(QHostAddress::AnyIPv4, port, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint); ``` 5. 接下来,使用QUdpSocket的joinMulticastGroup()函数加入到指定的组播组。例如: ```cpp udpSocket->joinMulticastGroup(QHostAddress(groupAddress)); ``` 6. 然后,使用QUdpSocket的readyRead()信号与对应的槽函数关联,以便在有数据到达时触发接收处理。例如: ```cpp connect(udpSocket, SIGNAL(readyRead()), this, SLOT(processPendingDatagrams())); ``` 7. 在槽函数processPendingDatagrams()中,使用QUdpSocket的readDatagram()函数读取接收到的数据,并进行相应处理。例如: ```cpp QByteArray datagram; QHostAddress senderAddress; quint16 senderPort; while (udpSocket->hasPendingDatagrams()) { datagram.resize(udpSocket->pendingDatagramSize()); udpSocket->readDatagram(datagram.data(), datagram.size(), &senderAddress, &senderPort); // 在这里对接收到的数据进行处理 } ``` 8. 最后,在需要使用UDP组播接收功能的地方,创建UdpReceiver对象,并调用其receiveData()函数开始接收数据。 注意:在多线程环境下,应该确保每个线程都有自己独立的UdpReceiver对象和QUdpSocket实例,以避免线程间的冲突和竞争条件。 希望这些步骤能够帮助您实现Qt C++中多线程接收UDP组播的功能!如果您有任何问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值