1、分装成一个类
2、支持断线重连
3、接收数据和解析数据都在子线程做
Qt中定时器和子线程都可以用来实现多任务处理,但它们的实现方式和应用场景略有不同。定时器是一种基于事件循环机制的定时回调机制,可以在独立于主程序事件循环的情况下执行函数或方法。它通常适合于轻量级任务和GUI界面的一些更新操作,比如定时刷新页面或者定时更新数据。但如果任务过于占用资源或者需要频繁的交互操作,则会影响GUI的响应速度以及程序的执行效率。而子线程则是一种独立于主线程的执行方式,可以用来执行一些大型或长时间的任务。它具有占用独立的计算资源以及避免GUI线程卡死等优点。通常适合于计算密集型的任务、网络请求、文件操作、数据库等IO操作等,可以避免GUI界面的阻塞和提高程序执行的效率。因此,如果你需要执行比较轻量级的任务且需要一定的时间间隔来执行,那么定时器会是一个不错的选择。如果你需要执行比较复杂或占用资源较多的任务,那么就需要使用子线程来避免对主线程的影响。
在Qt中搭建TCP客户端,接收数据时,通过阻塞式调用的方式会导致程序卡死,所以建议使用异步方式接收数据。一种常用的方法是将QTcpSocket
对象的readyRead()
信号连接到槽函数,然后在槽函数中读取数据。这样当有新数据到来时,会触发readyRead()
信号,槽函数会立即执行,读取数据并处理。但是这里需要注意的是,readyRead()
信号属于QTcpSocket
对象的信号,也就是运行在主线程中的信号。如果你在槽函数中做了一些比较耗时的操作,比如解析数据、文件操作等,会导致主线程的阻塞,并影响整个应用程序的性能和响应速度。因此,为了避免主线程的阻塞和提高程序的性能,建议将读取数据和处理数据的操作放在子线程中进行。一种常用的实现方式是通过创建一个继承自QThread
的子线程类,在其中实现读取和处理数据的操作,并将readyRead()
信号连接到子线程中的槽函数。这样当有新数据到来时,readyRead()
信号会触发子线程中的槽函数,在子线程中读取和处理数据,从而避免了主线程的阻塞。总之,为了保证程序的性能和响应速度,接收数据可以使用异步方式,将读取数据和处理数据的操作放在子线程中进行,从而避免在主线程中做一些耗时的操作。
#ifndef TCPCLIENT_H
#define TCPCLIENT_H
#include <QTcpSocket>
#include <QDateTime>
#include <QThread>
#include <QTimer>
#include "globle.h"
class TcpClient : public QThread
{
Q_OBJECT
public:
TcpClient();
~TcpClient();
QString m_ip = "192.168.8.128";
uint32_t m_port = 9999;
void StartReciveData();
void StopReciveData();
private:
int m_reconnect_flag = 1;//1 表示需要重连 0表示不需要
QTcpSocket * m_clientsocket;
QTimer* reconnect_timer;// 定时器,关于重连的
private slots:
virtual void run() override;
void InitNetWorkConnect(); //初始化一些连接connnect
void ReconnectNetWork(); //重连的槽函数
void ReciveNetData(); //接收到数据后,处理数据的槽函数
void QuitThread(); //优雅退出线程的函数
signals:
void signalTcpData(); //解析完数据后,emit该信号
};
#endif // TCPCLIENT_H
#include "tcpclient.h"
TcpClient::TcpClient()
{
qDebug()<<"TcpClient构建了";
}
TcpClient::~TcpClient()
{
qDebug()<<"TcpClient西沟了";
QuitThread();
}
void TcpClient::StartReciveData()
{
this->start();
}
void TcpClient::StopReciveData()
{
QuitThread();
}
void TcpClient::run()
{
qDebug()<<"TcpClient子线程开始";
//默认为Tcp通讯
m_clientsocket = new QTcpSocket;
//定义重连定时器
reconnect_timer = new QTimer;
InitNetWorkConnect();
m_clientsocket->connectToHost(m_ip,m_port);
reconnect_timer->start(3000);
exec();
delete m_clientsocket;
m_clientsocket = nullptr;
delete reconnect_timer;
reconnect_timer = nullptr;
}
void TcpClient::InitNetWorkConnect()
{
connect(m_clientsocket,&QTcpSocket::connected,this,[=](){
qDebug()<<QDateTime::currentDateTime().toString("hh:mm:ss.zzzz");
qDebug()<<"成功建立连接...";
m_reconnect_flag = 0;
},Qt::DirectConnection);
connect(m_clientsocket,&QTcpSocket::disconnected,this,[=]{
qDebug()<<QDateTime::currentDateTime().toString("hh:mm:ss.zzzz");
qDebug()<<"成功断开连接...";
m_reconnect_flag = 1;
},Qt::DirectConnection);
connect(reconnect_timer,&QTimer::timeout,this,&TcpClient::ReconnectNetWork,Qt::DirectConnection);
// //接受数据的connect
connect(m_clientsocket,&QTcpSocket::readyRead,this,&TcpClient::ReciveNetData,Qt::DirectConnection);
}
void TcpClient::ReconnectNetWork()
{
//如果通讯类型是TCP且需要从连
if(g_comms_type==0&&m_reconnect_flag==1)
{
m_clientsocket->connectToHost(m_ip,m_port);
}
else
return ;
}
//将readyRead()信号连接到子线程中的槽函数
void TcpClient::ReciveNetData()
{
QString message = m_clientsocket->readAll();
qDebug()<<"recive = "<<message;
//解包
//发送解包后的数据
}
void TcpClient::QuitThread()
{
if(this->isRunning())
{
this->quit();
this->wait();
}
else
{
}
return;
}