Qt實(shí)現(xiàn)UDP多線程數(shù)據(jù)處理及發(fā)送的簡(jiǎn)單實(shí)例
邏輯與運(yùn)行
程序邏輯圖如下:

接收端運(yùn)行截圖如下:

客戶端接收數(shù)據(jù)如下:
客戶端用的是串口調(diào)試工具:

源碼
程序結(jié)構(gòu)如下:

源碼如下:
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) + "發(fā)來(lái)數(shù)據(jù)包, 正在處理數(shù)據(jù)";
return msg;
}
};
class UDPMsgSender:public UDPMsg{
public:
QString backFunction(const PeerIP *peerIP){
QHostAddress address(peerIP->IPv4Address);
QString msg = "已發(fā)送到IP:" + address.toString() + " 端口:" + QString::number(peerIP->port) + "UDP數(shù)據(jù)包,準(zhǔn)備發(fā)送數(shù)據(jù)";
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);
}
}
到此這篇關(guān)于Qt實(shí)現(xiàn)UDP多線程數(shù)據(jù)處理及發(fā)送的簡(jiǎn)單實(shí)例的文章就介紹到這了,更多相關(guān)Qt UDP多線程發(fā)送內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++實(shí)現(xiàn)LeetCode(141.單鏈表中的環(huán))
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(141.單鏈表中的環(huán)),本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07
C++多態(tài)特性之派生與虛函數(shù)與模板詳細(xì)介紹
這篇文章主要介紹了C++多態(tài)的特性派生與虛函數(shù)與模板,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧2022-09-09
VS2022永久配置OpenCV開(kāi)發(fā)環(huán)境的實(shí)現(xiàn)
本文主要介紹了VS2022永久配置OpenCV開(kāi)發(fā)環(huán)境的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02
C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單的通訊錄
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單的通訊錄,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-02-02

