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!