目录
逻辑与运行
源码
程序逻辑图如下:
接收端运行截图如下:
客户端接收数据如下:
客户端用的是串口调试工具:
程序结构如下:
源码如下:
data.h
#ifndef DATA_H
#define DATA_H
#include
#include
#include
#include
#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
#include
#include
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 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
#include
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 m_peerIP;
MsgQueue *m_sender;
MsgQueue *m_receiv;
};
#endif // WIDGET_H
main.cpp
#include "widget.h"
#include
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
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
#include
#include
#include
#include
#include
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);
}
}