Qt实现UDP多线程数据处理及发送的简单实例
短信预约 -IT技能 免费直播动态提醒
逻辑与运行
程序逻辑图如下:
接收端运行截图如下:
客户端接收数据如下:
客户端用的是串口调试工具:
源码
程序结构如下:
源码如下:
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 class="lazy" data-srcAddress;
quint16 nclass="lazy" data-srcPort;
QByteArray datagram;
datagram.resize(m_udpSocket->pendingDatagramSize());
m_udpSocket->readDatagram(datagram.data(), datagram.size(), &class="lazy" data-srcAddress, &nclass="lazy" data-srcPort);;
canAppendInList(class="lazy" data-srcAddress.toIPv4Address(), nclass="lazy" data-srcPort);
}
}
到此这篇关于Qt实现UDP多线程数据处理及发送的简单实例的文章就介绍到这了,更多相关Qt UDP多线程发送内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341