基于Qt多线程实现UDP通信

基于Qt多线程实现UDP通信# 演示先演示,在展开如何实现,本次代码在windows、linux、mac都可使用。大家不能光看,实际敲一敲,敲出强大,敲出好工作。简单理解:服务器-》发送hello-》客户端也可以不写客户端或者服务器之一,使用以下调试工具即可。

大家好,欢迎来到IT知识分享网。

# 演示

先演示,在展开如何实现,本次代码在windows、linux、mac都可使用。

大家不能光看,实际敲一敲,敲出强大,敲出好工作。

简单理解:服务器-》发送hello-》客户端

基于Qt多线程实现UDP通信

也可以不写客户端或者服务器之一,使用以下调试工具即可。

虚拟串口+串口助手+UDP和TCP调试助手[编程人员必备]

# UDP

由于要使用套接字,所以需要在服务器和客户端的工程文件中都添加

QT += core gui network

使用writeDatagram方法传输数据,readDatagram方法接收数据。QT在调用writeDatagram方法时候会自动发出readyRead信号给接收方监听。

基于Qt多线程实现UDP通信

# 多线程

Qt有两种多线程的方法,其中一种是继承QThreadrun函数,另外一种是把一个继承于QObject的类转移到一个Thread里,即使用MoveToThread。

  Qt4.8之前都是使用继承QThreadrun这种方法,但是Qt4.8之后,Qt官方建议使用第二种方法。因此本文使用的是第二种方法。

  第二种方法主要就是写一个一个继承于QObject的类,将耗时的工作写在该类的槽函数中。

然后将派生类对象移动到一个QThread中,该线程需要start。最后,通过信号连接派生类的槽函数,并通过信号触发槽函数。(槽函数在子线程中执行)。

基于Qt多线程实现UDP通信

先把ui界面贴一下,其中label名字叫做label_tosend,按钮名字pushbutton_start。

# 服务器实现

## 套接字头文件

 #ifndef TRAVEL_H #define TRAVEL_H #include <QObject> #include <QDebug> #include <QString> #include <QUdpSocket> class travel : public QObject { Q_OBJECT public: explicit travel(QObject *parent = nullptr); ~travel(); signals: void sig_ok(); public slots: void slot_do(QString msg,int port); //主要实现功能的函数,用于传送数据给客户端,其中两个传入参数分别是待传数据和客户端端口号 private: QUdpSocket *mudpsocket; }; #endif // TRAVEL_H

【文章福利】Qt开发学习资料包、大厂面试题、技术视频和学习路线图,包括(Qt C++基础,数据库编程,Qt项目实战、Qt框架、QML、Opencv、qt线程等等)有需要的可以进企鹅裙领取哦~

基于Qt多线程实现UDP通信

## 套接字源文件

 // 接下来是traval.cpp #include "travel.h" #include <QUdpSocket> #include <QThread> travel::travel(QObject *parent) : QObject(parent) { qDebug()<<"构造了travel"; mudpsocket=new QUdpSocket(this);//新建一个UDP套接字 } travel::~travel() { qDebug()<<"析构了travel"; } void travel::slot_do(QString msg,int port) {   //writeDatagram方法传入4个参数,分别是数据,数据大小,接收端ip,接收端端口   //如果传输成功,该方法返回传输数据的大小(字节),如果失败返回-1 int len=mudpsocket->writeDatagram(msg.toUtf8(),msg.length(),QHostAddress::Broadcast,port); if(len!=msg.length()) {return;} qDebug()<<"开启线程"<<QThread::currentThreadId();//查看槽函数在哪个线程运行 emit sig_ok();//发出我已经传输完毕的信号 }

## 服务器udphost.h

#ifndef UDPHOST_H #define UDPHOST_H #include <QWidget> #include "travel.h" #include <QThread> #include <QString> QT_BEGIN_NAMESPACE namespace Ui { class UdpHost; } QT_END_NAMESPACE class UdpHost : public QWidget { Q_OBJECT public: UdpHost(QWidget *parent = nullptr); ~UdpHost(); signals: void sig_dowork(QString,int); private slots: void on_pushButton_start_clicked(); public slots: void slot_finish(); private: Ui::UdpHost *ui; travel *traveltoclient; QThread *thread; }; #endif // UDPHOST_H

这是一个UDP主机的头文件实现,它包括以下功能:

1. 实现了一个继承自QWidgetUdpHost类,用于显示UDP主机的界面。

2. 在构造函数中初始化了界面和相关变量。

3. 定义了一个信号sig_dowork,用于发送工作请求给travel类。

4. 定义了一个槽函数slot_finish,用于处理工作完成的信号。

5. 定义了一个私有成员变量traveltoclient,表示与客户端通信的travel类的实例。

6. 定义了一个私有成员变量thread,表示用于执行travel类的线程。

在界面上,有一个开始按钮,点击该按钮会触发槽函数on_pushButton_start_clicked(),用于发送工作请求给travel类。当工作完成时,会触发槽函数slot_finish(),用于处理工作完成的信号。

通过使用这个头文件,你可以方便地创建一个UDP主机的界面,并实现与客户端的通信功能。

## 服务器udphost.cpp

 #include "udphost.h" #include "ui_udphost.h" #include <QDebug> #include <QString> UdpHost::UdpHost(QWidget *parent) : QWidget(parent) , ui(new Ui::UdpHost) { qDebug()<<"主线程:"<<QThread::currentThreadId(); ui->setupUi(this); traveltoclient=new travel();//创建对象 thread=new QThread();//创建线程 traveltoclient->moveToThread(thread);//使用该方法实现多线程,这是QT推荐的 connect(thread,&QThread::finished,traveltoclient,&QObject::deleteLater); connect(this,&UdpHost::sig_dowork,traveltoclient,&travel::slot_do); //用connect的方式调用do函数,否则多线程报错 connect(traveltoclient,&travel::sig_ok,this,&UdpHost::slot_finish); } UdpHost::~UdpHost() { delete ui; //关闭子线程 thread->quit(); thread->wait(); } void UdpHost::on_pushButton_start_clicked() { thread->start(); QString msg=ui->label_tosend->text(); emit sig_dowork(msg,6666);//把数据和端口号作为参数传出去 } void UdpHost::slot_finish() { qDebug()<<"结束"<<QThread::currentThreadId(); }

# 客户端的代码

基于Qt多线程实现UDP通信

客户端的ui里就放了一个label用来显示接收到的数据,名字是label_get。

## 客户端的头文件

 #ifndef UDPCLIENT_H #define UDPCLIENT_H #include <QWidget> #include <QUdpSocket> QT_BEGIN_NAMESPACE namespace Ui { class udpClient; } QT_END_NAMESPACE class udpClient : public QWidget { Q_OBJECT public: udpClient(QWidget *parent = nullptr); ~udpClient(); public slots: void slot_received();//用来处理接收到的数据 private: Ui::udpClient *ui; QUdpSocket *mudpsocket; }; #endif // UDPCLIENT_H

这是一个UDP客户端的头文件实现,它包括以下功能:

  • 1. 实现了一个继承自QWidgetudpClient类,用于显示UDP客户端的界面。
  • 2. 在构造函数中初始化了界面和相关变量。
  • 3. 定义了一个槽函数slot_received,用于处理接收到的数据。
  • 4. 定义了一个私有成员变量mudpsocket,表示用于进行UDP通信的QUdpSocket类的实例。

在界面上,没有提供发送数据的按钮,因此该UDP客户端主要用于接收数据。当接收到数据时,会触发槽函数slot_received,用于处理接收到的数据。

通过使用这个头文件,你可以方便地创建一个UDP客户端的界面,并实现接收数据的功能。

## 客户端的CPP代码

 #include "udpclient.h" #include "ui_udpclient.h" #include <QByteArray> udpClient::udpClient(QWidget *parent) : QWidget(parent) , ui(new Ui::udpClient) { ui->setupUi(this); mudpsocket=new QUdpSocket(this); mudpsocket->bind(6666); connect(mudpsocket,&QUdpSocket::readyRead,this,&udpClient::slot_received); //监听readRead信号 } udpClient::~udpClient() { delete ui; } void udpClient::slot_received() { while(mudpsocket->hasPendingDatagrams()) { QByteArray datagram; //为避免数据丢失,在尝试读取之前,调用pendingDatagramSize()确定未决数据报的大小 datagram.resize(mudpsocket->pendingDatagramSize()); //读取数据,该方法传入四个参数,后面两个可以为空,分别是数据,数据的最大大小,地址和端口 mudpsocket->readDatagram(datagram.data(),datagram.size()); QString msg=datagram.data(); ui->label_get->setText(msg);//显示收到的数据 } }

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/84994.html

(0)

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

关注微信