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多线程发送内容请搜索编程宝库以前的文章,希望大家多多支持编程宝库!
模板由于模板元编程需要以面向对象为基础,所以如有疑问之处可以先补充一点C++面向对象的知识:C++面向对象这一篇就够了泛型初步由于C++是静态强类型语言,所以变量一经创建,则类型不得更改。如果我们希望创建一 ...