逻辑与运行
程序逻辑图如下:
接收端运行截图如下:
客户端接收数据如下:
客户端用的是串口调试工具:
源码
程序结构如下:
源码如下:
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多线程发送内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!