当前位置:   article > 正文

基于Qt多线程实现UDP通信_qt udp多线程通信

qt udp多线程通信

# 演示

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

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

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

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

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

# UDP

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

QT += core gui network

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

# 多线程

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

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

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

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

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

# 服务器实现

## 套接字头文件

  1. #ifndef TRAVEL_H
  2. #define TRAVEL_H
  3. #include <QObject>
  4. #include <QDebug>
  5. #include <QString>
  6. #include <QUdpSocket>
  7. class travel : public QObject
  8. {
  9. Q_OBJECT
  10. public:
  11. explicit travel(QObject *parent = nullptr);
  12. ~travel();
  13. signals:
  14. void sig_ok();
  15. public slots:
  16. void slot_do(QString msg,int port);
  17. //主要实现功能的函数,用于传送数据给客户端,其中两个传入参数分别是待传数据和客户端端口号
  18. private:
  19. QUdpSocket *mudpsocket;
  20. };
  21. #endif // TRAVEL_H

## 套接字源文件

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

## 服务器udphost.h

  1. #ifndef UDPHOST_H
  2. #define UDPHOST_H
  3. #include <QWidget>
  4. #include "travel.h"
  5. #include <QThread>
  6. #include <QString>
  7. QT_BEGIN_NAMESPACE
  8. namespace Ui { class UdpHost; }
  9. QT_END_NAMESPACE
  10. class UdpHost : public QWidget
  11. {
  12. Q_OBJECT
  13. public:
  14. UdpHost(QWidget *parent = nullptr);
  15. ~UdpHost();
  16. signals:
  17. void sig_dowork(QString,int);
  18. private slots:
  19. void on_pushButton_start_clicked();
  20. public slots:
  21. void slot_finish();
  22. private:
  23. Ui::UdpHost *ui;
  24. travel *traveltoclient;
  25. QThread *thread;
  26. };
  27. #endif // UDPHOST_H

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

1. 实现了一个继承自QWidget的UdpHost类,用于显示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

  1. #include "udphost.h"
  2. #include "ui_udphost.h"
  3. #include <QDebug>
  4. #include <QString>
  5. UdpHost::UdpHost(QWidget *parent)
  6. : QWidget(parent)
  7. , ui(new Ui::UdpHost)
  8. {
  9. qDebug()<<"主线程:"<<QThread::currentThreadId();
  10. ui->setupUi(this);
  11. traveltoclient=new travel();//创建对象
  12. thread=new QThread();//创建线程
  13. traveltoclient->moveToThread(thread);//使用该方法实现多线程,这是QT推荐的
  14. connect(thread,&QThread::finished,traveltoclient,&QObject::deleteLater);
  15. connect(this,&UdpHost::sig_dowork,traveltoclient,&travel::slot_do);
  16. //用connect的方式调用do函数,否则多线程报错
  17. connect(traveltoclient,&travel::sig_ok,this,&UdpHost::slot_finish);
  18. }
  19. UdpHost::~UdpHost()
  20. {
  21. delete ui;
  22. //关闭子线程
  23. thread->quit();
  24. thread->wait();
  25. }
  26. void UdpHost::on_pushButton_start_clicked()
  27. {
  28. thread->start();
  29. QString msg=ui->label_tosend->text();
  30. emit sig_dowork(msg,6666);//把数据和端口号作为参数传出去
  31. }
  32. void UdpHost::slot_finish()
  33. {
  34. qDebug()<<"结束"<<QThread::currentThreadId();
  35. }

# 客户端的代码


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

## 客户端的头文件

  1. #ifndef UDPCLIENT_H
  2. #define UDPCLIENT_H
  3. #include <QWidget>
  4. #include <QUdpSocket>
  5. QT_BEGIN_NAMESPACE
  6. namespace Ui { class udpClient; }
  7. QT_END_NAMESPACE
  8. class udpClient : public QWidget
  9. {
  10. Q_OBJECT
  11. public:
  12. udpClient(QWidget *parent = nullptr);
  13. ~udpClient();
  14. public slots:
  15. void slot_received();//用来处理接收到的数据
  16. private:
  17. Ui::udpClient *ui;
  18. QUdpSocket *mudpsocket;
  19. };
  20. #endif // UDPCLIENT_H

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

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

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

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

## 客户端的CPP代码

  1. #include "udpclient.h"
  2. #include "ui_udpclient.h"
  3. #include <QByteArray>
  4. udpClient::udpClient(QWidget *parent)
  5. : QWidget(parent)
  6. , ui(new Ui::udpClient)
  7. {
  8. ui->setupUi(this);
  9. mudpsocket=new QUdpSocket(this);
  10. mudpsocket->bind(6666);
  11. connect(mudpsocket,&QUdpSocket::readyRead,this,&udpClient::slot_received);
  12. //监听readRead信号
  13. }
  14. udpClient::~udpClient()
  15. {
  16. delete ui;
  17. }
  18. void udpClient::slot_received()
  19. {
  20. while(mudpsocket->hasPendingDatagrams())
  21. {
  22. QByteArray datagram;
  23. //为避免数据丢失,在尝试读取之前,调用pendingDatagramSize()确定未决数据报的大小
  24. datagram.resize(mudpsocket->pendingDatagramSize());
  25. //读取数据,该方法传入四个参数,后面两个可以为空,分别是数据,数据的最大大小,地址和端口
  26. mudpsocket->readDatagram(datagram.data(),datagram.size());
  27. QString msg=datagram.data();
  28. ui->label_get->setText(msg);//显示收到的数据
  29. }
  30. }

本文福利,费领取Qt开发学习资料包、技术视频,内容包括(Qt实战项目视频教程+代码,C++语言基础,C++设计模式,Qt编程入门,QT信号与槽机制,QT界面开发-图像绘制,QT网络,QT数据库编程,QT项目实战,QSS,OpenCV,Quick模块,面试题等等)↓↓↓↓↓↓见下面↓↓文章底部点击费领取↓↓

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/627138
推荐阅读
相关标签
  

闽ICP备14008679号