• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

Qt UDP 单独在子线程执行

武飞扬头像
Mr.codeee
帮助1

一.需要用到的类

QThread和QUDPSocket

.pro文件中需要引入模块

QT  = network

常用接口:

1.bool bind(quint16 port = 0, BindMode mode = DefaultForPlatform) ;//绑定端口

2.qint64 writeDatagram(const QByteArray &datagram, const QHostAddress &host, quint16 port);//发送数据

3.void abort() ;//关闭连接

4.qint64 readDatagram(char *data, qint64 maxSize, QHostAddress *address = Q_NULLPTR, quint16 *port = Q_NULLPTR);//读数据

每当有数据接收的时候,QUdpSocket都会发送 readyRead()信号,只需要绑定上槽就能接收到数据。

二.server work类

此类的作用主要实现UDP之间的通信,直接上代码。

  1.  
    //WUDPServerWorker.h
  2.  
     
  3.  
    #ifndef WUDPSERVERWORKER_H
  4.  
    #define WUDPSERVERWORKER_H
  5.  
     
  6.  
    #include <QObject>
  7.  
    #include <QUdpSocket>
  8.  
     
  9.  
    class WUDPServerWorker : public QObject
  10.  
    {
  11.  
    Q_OBJECT
  12.  
    public:
  13.  
    explicit WUDPServerWorker(QObject *parent = nullptr);
  14.  
    ~WUDPServerWorker();
  15.  
     
  16.  
    public slots:
  17.  
    //绑定槽函数
  18.  
    void slotBind(quint16 port);
  19.  
     
  20.  
    void slotBind(QString ip,quint16 port);
  21.  
     
  22.  
    void slotUnBind();
  23.  
     
  24.  
    void slotSendDatagram(const QByteArray &data,const QHostAddress &host, quint16 port);
  25.  
     
  26.  
    public:
  27.  
    //绑定端口
  28.  
    bool bind(quint16 port = 0, QUdpSocket::BindMode mode = QUdpSocket::DefaultForPlatform);
  29.  
     
  30.  
    bool bind(const QHostAddress &address, quint16 port = 0, QUdpSocket::BindMode mode = QUdpSocket::DefaultForPlatform);
  31.  
     
  32.  
    //解绑端口
  33.  
    void unBind();
  34.  
     
  35.  
    //发送数据
  36.  
    qint64 sendDatagram(const char *data, qint64 len, const QHostAddress &host, quint16 port);
  37.  
     
  38.  
    //发送数据
  39.  
    qint64 sendDatagram(const QByteArray &data,const QHostAddress &host, quint16 port);
  40.  
     
  41.  
    signals:
  42.  
    //发送UDP数据
  43.  
    void sigReceiveData(const QByteArray &byte);
  44.  
     
  45.  
    private slots:
  46.  
    //收到UDP数据
  47.  
    void slotReadyRead();
  48.  
     
  49.  
    private:
  50.  
    QUdpSocket *m_udpSocket = nullptr; //UDP socket
  51.  
    };
  52.  
     
  53.  
     
  54.  
     
  55.  
    /WUDPServerWorker.cpp
  56.  
    #include "WUdpServerWorker.h"
  57.  
    #include <QDebug>
  58.  
    #include <QThread>
  59.  
     
  60.  
    WUDPServerWorker::WUDPServerWorker(QObject *parent)
  61.  
    : QObject(parent)
  62.  
    {
  63.  
    m_udpSocket = new QUdpSocket(this);
  64.  
    connect(m_udpSocket,SIGNAL(readyRead()),this,SLOT(slotReadyRead()));
  65.  
    }
  66.  
     
  67.  
    WUDPServerWorker::~WUDPServerWorker()
  68.  
    {
  69.  
    if(m_udpSocket)
  70.  
    {
  71.  
    unBind();
  72.  
    delete m_udpSocket;
  73.  
    }
  74.  
    }
  75.  
     
  76.  
    void WUDPServerWorker::slotBind(quint16 port)
  77.  
    {
  78.  
    bind(port);
  79.  
    }
  80.  
     
  81.  
    void WUDPServerWorker::slotBind(QString ip, quint16 port)
  82.  
    {
  83.  
    bind(QHostAddress(ip),port);
  84.  
    }
  85.  
     
  86.  
    void WUDPServerWorker::slotUnBind()
  87.  
    {
  88.  
    unBind();
  89.  
    }
  90.  
     
  91.  
    void WUDPServerWorker::slotSendDatagram(const QByteArray &data, const QHostAddress &host, quint16 port)
  92.  
    {
  93.  
    m_udpSocket->writeDatagram(data,host,port);
  94.  
    }
  95.  
     
  96.  
    bool WUDPServerWorker::bind(quint16 port, QAbstractSocket::BindMode mode)
  97.  
    {
  98.  
    return m_udpSocket->bind(port,mode);
  99.  
    }
  100.  
     
  101.  
    bool WUDPServerWorker::bind(const QHostAddress &address, quint16 port, QAbstractSocket::BindMode mode)
  102.  
    {
  103.  
    return m_udpSocket->bind(address,port,mode);
  104.  
    }
  105.  
     
  106.  
     
  107.  
    void WUDPServerWorker::unBind()
  108.  
    {
  109.  
    m_udpSocket->abort();
  110.  
    }
  111.  
     
  112.  
    qint64 WUDPServerWorker::sendDatagram(const char *data, qint64 len, const QHostAddress &host, quint16 port)
  113.  
    {
  114.  
    return m_udpSocket->writeDatagram(data,len,host,port);
  115.  
    }
  116.  
     
  117.  
    qint64 WUDPServerWorker::sendDatagram(const QByteArray &data, const QHostAddress &host, quint16 port)
  118.  
    {
  119.  
    return m_udpSocket->writeDatagram(data,host,port);
  120.  
    }
  121.  
     
  122.  
    void WUDPServerWorker::slotReadyRead()
  123.  
    {
  124.  
    //是否还有待读取的传入数据报
  125.  
    while(m_udpSocket->hasPendingDatagrams())
  126.  
    {
  127.  
    QByteArray data;
  128.  
     
  129.  
    //返回待读取的数据报的字节数
  130.  
    data.resize(m_udpSocket->pendingDatagramSize());
  131.  
     
  132.  
    QHostAddress peerAddr;
  133.  
     
  134.  
    quint16 peerPort;
  135.  
     
  136.  
    //读取数据报的内容
  137.  
    m_udpSocket->readDatagram(data.data(),data.size(),&peerAddr,&peerPort);
  138.  
     
  139.  
    QString port = QString::number(m_udpSocket->localPort());
  140.  
    QString peerStr = port " *****recieve udp data [From ] " peerAddr.toString() ":" QString::number(peerPort) "] ";
  141.  
    qDebug()<<peerStr;
  142.  
    qDebug()<<QThread::currentThreadId();
  143.  
     
  144.  
    emit sigReceiveData(data);
  145.  
    }
  146.  
    }
  147.  
     
  148.  
     

每当有数据收到后,会调用slotReadyRead()槽函数,然后readDatagram()读取数据,可以知道数据来源的地址和端口号。

三.server类

此类主要作用是让udp在单独线程运行,因为UDP在单独线程里面跑,所以通过信号-槽的方式,调用bind()、发送数据等方法。

  1.  
    #ifndef WUDPSERVER_H
  2.  
    #define WUDPSERVER_H
  3.  
     
  4.  
    #include <QObject>
  5.  
    #include <QThread>
  6.  
    #include <QHostAddress>
  7.  
    #include <QDebug>
  8.  
    #include <QUdpSocket>
  9.  
    #include <QTimer>
  10.  
     
  11.  
    class WUDPServerWorker;
  12.  
     
  13.  
    class WUDPServer : public QObject
  14.  
    {
  15.  
    Q_OBJECT
  16.  
    public:
  17.  
    explicit WUDPServer(QObject *parent = nullptr);
  18.  
    ~WUDPServer();
  19.  
     
  20.  
    signals:
  21.  
    void sigBind(quint16 port);
  22.  
     
  23.  
    void sigBind(QString ip,quint16 port);
  24.  
     
  25.  
    void sigUnBind();
  26.  
     
  27.  
    void sigSendDatagram(const QByteArray &data, const QHostAddress &host, quint16 port);
  28.  
     
  29.  
    public:
  30.  
    //发送数据
  31.  
    qint64 sendDatagram(const QByteArray &data, const QHostAddress &host, quint16 port);
  32.  
    //绑定端口
  33.  
    bool bind(quint16 port = 0, QUdpSocket::BindMode mode = QUdpSocket::DefaultForPlatform);
  34.  
     
  35.  
    bool bind(const QHostAddress &address, quint16 port = 0, QUdpSocket::BindMode mode = QUdpSocket::DefaultForPlatform);
  36.  
     
  37.  
    //解绑端口
  38.  
    void unBind();
  39.  
     
  40.  
    //开始线程
  41.  
    void start();
  42.  
     
  43.  
    private slots:
  44.  
    //收到UDP数据
  45.  
    void slotReceiveUdpData(const QByteArray&);
  46.  
     
  47.  
    private:
  48.  
    QThread m_workerThread; //UDP工作线程
  49.  
     
  50.  
    WUDPServerWorker *m_work = nullptr; //UDP工作类
  51.  
     
  52.  
    QTimer *m_timer = nullptr;
  53.  
    };
  54.  
     
  55.  
    #endif // WUDPSERVER_H
  56.  
     
  57.  
     
  58.  
     
  59.  
    ///WUDPServer.cpp
  60.  
     
  61.  
    #include "WUdpServer.h"
  62.  
    #include "WUdpServerWorker.h"
  63.  
    #include <QEventLoop>
  64.  
    WUDPServer::WUDPServer(QObject *parent)
  65.  
    : QObject(parent)
  66.  
    {
  67.  
    m_work = new WUDPServerWorker;
  68.  
     
  69.  
    m_work->moveToThread(&m_workerThread);
  70.  
    connect(this,SIGNAL(sigBind(QString,quint16)),m_work,SLOT(slotBind(QString,quint16)));
  71.  
    connect(this,SIGNAL(sigBind(quint16)),m_work,SLOT(slotBind(quint16)));
  72.  
    connect(this,SIGNAL(sigUnBind()),m_work,SLOT(slotUnBind()));
  73.  
    connect(this,&WUDPServer::sigSendDatagram,m_work,&WUDPServerWorker::slotSendDatagram);
  74.  
     
  75.  
    connect(&m_workerThread, &QThread::finished, m_work, &QObject::deleteLater);
  76.  
    connect(m_work,SIGNAL(sigReceiveData(QByteArray)),this,SLOT(slotReceiveUdpData(QByteArray)));
  77.  
    }
  78.  
     
  79.  
    WUDPServer::~WUDPServer()
  80.  
    {
  81.  
    m_workerThread.quit();
  82.  
    m_workerThread.wait();
  83.  
    }
  84.  
     
  85.  
    qint64 WUDPServer::sendDatagram(const QByteArray &data, const QHostAddress &host, quint16 port)
  86.  
    {
  87.  
    emit sigSendDatagram(data,host,port);
  88.  
    }
  89.  
     
  90.  
    bool WUDPServer::bind(quint16 port, QUdpSocket::BindMode mode)
  91.  
    {
  92.  
    Q_UNUSED(mode);
  93.  
    emit sigBind(port);
  94.  
    }
  95.  
     
  96.  
    bool WUDPServer::bind(const QHostAddress &address, quint16 port, QUdpSocket::BindMode mode)
  97.  
    {
  98.  
    Q_UNUSED(mode);
  99.  
    emit sigBind(address.toString(),port);
  100.  
    }
  101.  
     
  102.  
    void WUDPServer::unBind()
  103.  
    {
  104.  
    emit sigUnBind();
  105.  
    }
  106.  
     
  107.  
    void WUDPServer::start()
  108.  
    {
  109.  
    m_workerThread.start();
  110.  
    }
  111.  
     
  112.  
    void WUDPServer::slotReceiveUdpData(const QByteArray& byte)
  113.  
    {
  114.  
    //处理数据
  115.  
    qDebug()<<byte;
  116.  
    }
  117.  
     
  118.  
     

在类中创建了一个线程,将WUDPServerWorker对象放在线程中运行,调用moveToThread()方法即可,需要绑定两个槽,

connect(&m_workerThread,&QThread::finished,&m_workerThread,&QObject::deleteLater)
connect(&m_workerThread, &QThread::finished, m_work, &QObject::deleteLater);

在线程完成后,释放资源,不但要释放线程本身,还需要释放WUDPServerWorker对象。

在程序退出时需要调用以下方法,优雅的结束线程。

m_workerThread.quit();
m_workerThread.wait();

使用方法:

  1.  
    WUDPServer *server = new WUDPServer(this);
  2.  
    server->start();
  3.  
    server->bind(8888);

四.更多参考

QT UDP通信

QT 多线程 

五.源码

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgbeehh
系列文章
更多 icon
同类精品
更多 icon
继续加载