IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> Qt 自定义多线程UDP Server类 -> 正文阅读

[网络协议]Qt 自定义多线程UDP Server类

一.需要用到的类

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之间的通信,直接上代码。

//WUDPServerWorker.h

#ifndef WUDPSERVERWORKER_H
#define WUDPSERVERWORKER_H

#include <QObject>
#include <QUdpSocket>

class WUDPServerWorker : public QObject
{
    Q_OBJECT
public:
    explicit WUDPServerWorker(QObject *parent = nullptr);
    ~WUDPServerWorker();

public:
    //绑定端口
    bool bind(qint16 port);

    //解绑端口
    void unBind();

    //发送数据
    qint64 sendDatagram(const char *data, qint64 len, const QHostAddress &host, quint16 port);

    //发送数据
    qint64 sendDatagram(const QByteArray &data,const QHostAddress &host, quint16 port);

signals:
    //发送UDP数据
    void sigReceiveData(const QByteArray &byte);

private slots:
    //收到UDP数据
    void slotReadyRead();

private:
    QUdpSocket *m_udpSocket = nullptr;  //UDP socket
};

#endif // WUDPSERVERWORKER_H



/WUDPServerWorker.cpp


#include "WUdpServerWorker.h"
#include <QDebug>

WUDPServerWorker::WUDPServerWorker(QObject *parent)
    : QObject(parent)
{
    m_udpSocket = new QUdpSocket(this);
    connect(m_udpSocket,SIGNAL(readyRead()),this,SLOT(slotReadyRead()));
}

WUDPServerWorker::~WUDPServerWorker()
{
    if(m_udpSocket)
    {
        unBind();
        delete m_udpSocket;
    }
}

bool WUDPServerWorker::bind(qint16 port)
{
    return m_udpSocket->bind(port);
}

void WUDPServerWorker::unBind()
{
    if(m_udpSocket)
        m_udpSocket->abort();
}

qint64 WUDPServerWorker::sendDatagram(const char *data, qint64 len, const QHostAddress &host, quint16 port)
{
    return m_udpSocket->writeDatagram(data,len,host,port);
}

qint64 WUDPServerWorker::sendDatagram(const QByteArray &data, const QHostAddress &host, quint16 port)
{
    return m_udpSocket->writeDatagram(data,host,port);
}

void WUDPServerWorker::slotReadyRead()
{
    //是否还有待读取的传入数据报
   while(m_udpSocket->hasPendingDatagrams())
   {
       QByteArray data;

       //返回待读取的数据报的字节数
       data.resize(m_udpSocket->pendingDatagramSize());

       QHostAddress peerAddr;

       quint16 peerPort;

       //读取数据报的内容
       m_udpSocket->readDatagram(data.data(),data.size(),&peerAddr,&peerPort);

       QString port = QString::number(m_udpSocket->localPort());
       QString peerStr = port  + " *****recieve udp data [From ] +"+peerAddr.toString()+":"+QString::number(peerPort)+"] ";
       qDebug()<<peerStr;

       emit sigReceiveData(data);
   }
}

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

三.server类

此类主要作用是让udp在单独线程运行。

//WUDPServer.h

#ifndef WUDPSERVER_H
#define WUDPSERVER_H

#include <QObject>
#include <QThread>
#include <QHostAddress>
#include <QDebug>

class WUDPServerWorker;

class WUDPServer : public QObject
{
    Q_OBJECT
public:
    explicit WUDPServer(qint16 port = 0,QObject *parent = nullptr);
    ~WUDPServer();

public:
    //发送数据
    qint64 sendDatagram(const char *data, qint64 len, const QHostAddress &host, quint16 port);

    //发送数据
    qint64 sendDatagram(const QByteArray &data, const QHostAddress &host, quint16 port);

    //开始线程
    void start();

private slots:
    //收到UDP数据
    void slotReceiveUdpData(const QByteArray&);

private:
    QThread m_workerThread; //UDP工作线程

    WUDPServerWorker *m_work = nullptr;    //UDP工作类
};

#endif // WUDPSERVER_H



///WUDPServer.cpp

#include "WUdpServer.h"
#include "WUdpServerWorker.h"

WUDPServer::WUDPServer(qint16 port,QObject *parent)
    : QObject(parent)
{
    m_work = new WUDPServerWorker;
    if(!m_work->bind(port))
    {
        qDebug()<<"(UdpServer::UdpServer)*****udp listen port ="<<port<<" error";
    }
    else
    {
        qDebug()<<"*****udp listen port ="<<port<<" success";
    }
    m_work->moveToThread(&m_workerThread);
    connect(&m_workerThread, &QThread::finished, &m_workerThread,&QObject::deleteLater);
    connect(&m_workerThread, &QThread::finished, m_work, &QObject::deleteLater);
    connect(m_work,SIGNAL(sigReceiveData(QByteArray)),this,SLOT(slotReceiveUdpData(QByteArray)));
}

WUDPServer::~WUDPServer()
{
    m_workerThread.quit();
    m_workerThread.wait();
}

qint64 WUDPServer::sendDatagram(const char *data, qint64 len, const QHostAddress &host, quint16 port)
{
    return m_work->sendDatagram(data,len,host,port);
}

qint64 WUDPServer::sendDatagram(const QByteArray &data, const QHostAddress &host, quint16 port)
{
    return m_work->sendDatagram(data,host,port);
}

void WUDPServer::start()
{
    m_workerThread.start();
}

void WUDPServer::slotReceiveUdpData(const QByteArray& byte)
{
    //处理数据
    qDebug()<<byte;
}


在类中创建了一个线程,将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();

使用方法:

    WUDPServer *server = new WUDPServer(8888,nullptr);
    server->start();

四.更多参考

QT UDP通信

QT 多线程?

五.源码

源码包

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2022-03-17 22:35:21  更:2022-03-17 22:37:24 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 5:44:44-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码