Qt實現UDP多線程數據處理及發送的簡單實例

邏輯與運行

程序邏輯圖如下:

接收端運行截圖如下:

客戶端接收數據如下:

客戶端用的是串口調試工具:

源碼

程序結構如下:

源碼如下:

data.h

#ifndef DATA_H
#define DATA_H
 
#include <QObject>
#include <QHostAddress>
#include <QString>
#include <QDebug>
 
#define SenderListWidget 0
#define ReceviListWidget 1
 
class PeerIP{
public:
    quint32 IPv4Address;
    quint16 port;
 
    PeerIP(const quint32 Ip, const quint16 por){
 
        IPv4Address = Ip;
        port = por;
    }
 
    friend QDebug operator << (QDebug os, PeerIP peerIP){
 
        os << "(" << peerIP.IPv4Address << ", " << peerIP.port
           << ")";
 
        return os;
    }
};
 
 
class UDPMsg{
 
public:
    virtual QString backFunction(const PeerIP *peerIP){
 
        Q_UNUSED(peerIP)
        return "";
    }
 
protected:
    UDPMsg(){}
    virtual ~UDPMsg(){}
};
 
class UDPMsgReciver:public UDPMsg{
 
public:
    QString backFunction(const PeerIP *peerIP){
 
        QHostAddress address(peerIP->IPv4Address);
        QString msg = "接收到P:" + address.toString() + " 端口:" + QString::number(peerIP->port) + "發來數據包, 正在處理數據";
        return msg;
    }
};
 
class UDPMsgSender:public UDPMsg{
 
public:
    QString backFunction(const PeerIP *peerIP){
 
        QHostAddress address(peerIP->IPv4Address);
        QString msg = "已發送到IP:" + address.toString() + " 端口:" + QString::number(peerIP->port) + "UDP數據包,準備發送數據";
        return msg;
    }
};
 
#endif // DATA_H

msgqueue.h

#ifndef MSGQUEUE_H
#define MSGQUEUE_H
 
#include <QThread>
#include <QList>
#include <QWidget>
 
class PeerIP;
class UDPMsg;
class Widget;
 
 
class MsgQueue: public QThread
{
public:
    enum MsgType{RecvQueue, SendQueue};
    MsgQueue(Widget *widget, MsgType type);
    ~MsgQueue();
 
    void appendPeerIP(const quint32 ipV4, const quint16 port);
    void stop();
 
protected:
    void run();
 
private:
    QList<PeerIP*> m_list;
    MsgType m_type;
    bool m_canExit;
    UDPMsg *m_udpMsg;
    Widget *m_widget;
};
 
#endif // MSGQUEUE_H

widget.h

#ifndef WIDGET_H
#define WIDGET_H
 
#include <QWidget>
#include <QList>
 
QT_BEGIN_HEADER
class QUdpSocket;
QT_END_NAMESPACE
 
class PeerIP;
class MsgQueue;
 
namespace Ui {
class Widget;
}
 
class Widget : public QWidget
{
    Q_OBJECT
 
public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();
 
    void insertMsgInList(const int Type, const QString msg);
    void senderMsg(quint32 ipV4, quint16 port);
 
 
protected:
    void canAppendInList(const quint32 ipV4, const quint16 port);
    void closeEvent(QCloseEvent *event) Q_DECL_OVERRIDE;
 
protected slots:
    void readPendingDatagrams();
 
private:
    Ui::Widget *ui;
    QUdpSocket *m_udpSocket;
    QList<PeerIP*> m_peerIP;
 
    MsgQueue *m_sender;
    MsgQueue *m_receiv;
};
 
#endif // WIDGET_H

main.cpp

#include "widget.h"
#include <QApplication>
 
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();
 
    return a.exec();
}

msgqueue.cpp

#include "msgqueue.h"
#include "data.h"
#include "widget.h"
#include <QDebug>
 
MsgQueue::MsgQueue(Widget *widget, MsgType type):
    m_canExit(false)
{
    if(type == RecvQueue){
 
        m_udpMsg = new UDPMsgSender;
    }
    else{
 
        m_udpMsg = new UDPMsgReciver;
    }
    m_widget = widget;
    m_type = type;
    start();
}
 
MsgQueue::~MsgQueue()
{
    for(int i = 0; i < m_list.size(); i++){
 
        delete m_list[i];
    }
}
 
void MsgQueue::appendPeerIP(const quint32 ipV4, const quint16 port)
{
    PeerIP *peerIp = new PeerIP(ipV4, port);
    m_list.append(peerIp);
}
 
void MsgQueue::stop()
{
    m_canExit = true;
}
 
void MsgQueue::run()
{
    while(!m_canExit){
 
        for(int i = 0; i < m_list.size(); i++){
 
            QString msg = m_udpMsg->backFunction(m_list[i]);
            m_widget->insertMsgInList(m_type, msg);
 
            if(m_type == RecvQueue){
 
                //這裡可以寫後端處理
            }
            else{
 
                m_widget->senderMsg(m_list[i]->IPv4Address, m_list[i]->port);
            }
        }
        msleep(1000);
    }
}

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include "data.h"
#include "msgqueue.h"
#include <QUdpSocket>
#include <QNetworkDatagram>
#include <QHostAddress>
#include <QDebug>
#include <QEventLoop>
#include <QTimer>
 
 
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
 
    this->setWindowTitle("CSDN IT1995");
 
    m_udpSocket = new QUdpSocket(this);
 
    if(!m_udpSocket->bind(7755)){
 
        qDebug() << "bind failed! The assert will be triggred!";
        Q_ASSERT(!"bind failed!");
    }
 
    m_sender = new MsgQueue(this, MsgQueue::SendQueue);
    m_receiv = new MsgQueue(this, MsgQueue::RecvQueue);
 
    connect(m_udpSocket, SIGNAL(readyRead()), this, SLOT(readPendingDatagrams()));
}
 
Widget::~Widget()
{
    delete ui;
    delete m_sender;
    delete m_receiv;
    for(int i = 0; i < m_peerIP.size(); i++){
 
        delete m_peerIP[i];
    }
}
 
void Widget::insertMsgInList(const int Type, const QString msg)
{
    if(Type == SenderListWidget){
 
        ui->senderListWidget->insertItem(0, msg);
    }
    else{
 
        ui->receiverListWidget->insertItem(0, msg);
    }
}
 
void Widget::senderMsg(quint32 ipV4, quint16 port)
{
    QHostAddress address(ipV4);
    m_udpSocket->writeDatagram(QByteArray("I am fine, fuck you!"), address, port);
}
 
void Widget::canAppendInList(const quint32 ipV4, const quint16 port)
{
    for(int i = 0; i < m_peerIP.size(); i++){
 
        if(m_peerIP[i]->IPv4Address == ipV4 && m_peerIP[i]->port == port){
 
            qDebug() << "client in list";
            return;
        }
    }
    PeerIP *peerIP = new PeerIP(ipV4, port);
    m_peerIP.append(peerIP);
    m_sender->appendPeerIP(ipV4, port);
    m_receiv->appendPeerIP(ipV4, port);
}
 
void Widget::closeEvent(QCloseEvent *event)
{
    Q_UNUSED(event)
    m_sender->stop();
    m_receiv->stop();
 
    QEventLoop loop;
    QTimer::singleShot(1000, &loop, SLOT(quit()));
    loop.exec();
    this->close();
}
 
void Widget::readPendingDatagrams()
{
    while(m_udpSocket->hasPendingDatagrams()){
 
 
        QHostAddress srcAddress;
        quint16 nSrcPort;
        QByteArray datagram;
        datagram.resize(m_udpSocket->pendingDatagramSize());
        m_udpSocket->readDatagram(datagram.data(), datagram.size(), &srcAddress, &nSrcPort);;
        canAppendInList(srcAddress.toIPv4Address(), nSrcPort);
    }
}

到此這篇關於Qt實現UDP多線程數據處理及發送的簡單實例的文章就介紹到這瞭,更多相關Qt UDP多線程發送內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: