比较规范的Qt Tcp客户端类

       

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;
}

### 回答1: Qt是一个跨平台的C++应用程序开发框架,它提供了丰富的工具和库来开发图形界面、网络应用等各种功能。在Qt中,我们可以使用Qt网络模块来实现tcp客户端的封装。 在封装tcp客户端时,我们可以使用QtQTcpSocket来实现与服务器的通信。首先,我们需要创建一个QTcpSocket对象,并使用其connectToHost函数连接到服务器。连接成功后,我们可以使用write函数向服务器发送数据,并使用readyRead函数来监听服务器返回的数据。当有数据可读时,readyRead函数会被触发,我们可以使用readAll函数来读取服务器返回的数据。 为了使tcp客户端更易于使用和维护,我们可以将相关的操作封装到一个自定义的TcpClient中。在这个中,我们可以定义一些公有的接口,以供其他模块使用。例如,我们可以定义一个connectToServer函数来连接到服务器,一个sendData函数来发送数据,一个readData函数来读取数据等。在这些接口的实现中,我们可以调用QTcpSocket相应的函数来完成操作。 此外,为了提高tcp客户端的可靠性和健壮性,我们还可以在TcpClient中添加一些错误处理机制。例如,在连接服务器时,如果连接失败,我们可以触发一个错误信号,以便告知用户连接失败的原因。另外,我们还可以使用QTimer来实现超时机制,当一定时间内没有收到服务器的响应时,自动断开连接并触发相应的错误信号。 总之,使用Qt网络模块,我们可以很容易地封装tcp客户端,提供简洁易用的接口,并具备一定的错误处理机制,以便实现可靠的网络通信。 ### 回答2: QT是一款功能强大的跨平台应用程序开发框架,提供了丰富的网络编程支持。TCP是一种面向连接的网络传输协议,用于在不同主机之间进行可靠的数据传输。在QT中封装TCP客户端可以通过以下步骤实现: 1. 引入QT网络模块:在Qt工程文件中添加网络模块的依赖,例如在.pro文件中加入"QT += network",这样就可以使用QT提供的网络编程。 2. 创建客户端:可以新建一个来定义TCP客户端,可以继承自QT提供的QTcpSocket。在中可以定义一些成员变量和成员函数,例如连接服务器的IP地址和端口号等。 3. 实现连接服务器的函数:在客户端中实现连接服务器的函数,可以在该函数中使用QTcpSocket提供的connectToHost方法来与服务器建立连接。连接成功后可以在连接成功的信号槽函数中进行处理。 4. 实现数据收发功能:在客户端中可以实现发送和接收数据的函数,用于向服务器发送数据和接收服务器返回的数据。可以使用QTcpSocket提供的write和read方法来实现。也可以使用信号槽机制来处理数据的接收。 5. 处理断开连接:在客户端中可以实现断开连接的函数,用于与服务器断开连接。可以使用QTcpSocket提供的disconnectFromHost方法来断开连接。 6. 错误处理:在客户端中可以处理连接错误、数据发送错误等情况。可以使用QTcpSocket提供的error信号槽来处理错误。 通过以上步骤,可以封装一个基于QTTCP客户端,可以使用该客户端QT应用程序中实现与服务器的通信功能。 ### 回答3: Qt是一个功能强大且易于使用的跨平台开发框架,它提供了许多用于网络编程的和函数。使用Qt开发TCP客户端可以通过简单的封装来实现。 首先,我们需要创建一个继承自QTcpSocket的,用于封装TCP客户端的相关功能。这个应该具有连接服务器、发送数据和接收数据的功能。下面是一个简单的例子: class MyTcpClient : public QTcpSocket { Q_OBJECT public: explicit MyTcpClient(QObject *parent = nullptr); public slots: void connectToServer(const QString &ipAddress, quint16 port); void sendData(const QByteArray &data); private slots: void readData(); signals: void dataReceived(const QByteArray &data); private: QString m_ipAddress; quint16 m_port; }; 在MyTcpClient的构造函数中,我们可以设置一些初始值,如连接状态和服务器地址。 void MyTcpClient::connectToServer(const QString &ipAddress, quint16 port) { m_ipAddress = ipAddress; m_port = port; connectToHost(ipAddress, port); // 调用Qt提供的连接服务器函数 } void MyTcpClient::sendData(const QByteArray &data) { if (state() == QAbstractSocket::ConnectedState) { write(data); // 发送数据到服务器 flush(); } } void MyTcpClient::readData() { QByteArray data = readAll(); // 读取服务器发送的数据 emit dataReceived(data); // 发送信号,告诉外部有数据到达 } 在连接服务器之后,可以调用sendData函数发送数据到服务器。而接收数据则是通过继承QTcpSocket的readyRead信号来实现的,该信号在数据到达时触发readData函数。 在使用这个封装好的TCP客户端时,可以通过连接信号和槽来处理数据的收发。例如: MyTcpClient *client = new MyTcpClient(this); connect(client, &MyTcpClient::dataReceived, this, [](const QByteArray &data){ qDebug() << "Received data: " << data; }); client->connectToServer("127.0.0.1", 8888); client->sendData("Hello, server!"); 通过这样的封装,我们可以更加方便地使用Qt开发TCP客户端,简化了网络编程的过程。同时,这个封装也可以根据实际需求进行扩展,例如添加鉴权、错误处理等功能。总之,Qt提供的网络编程和函数使得TCP客户端的封装变得简单且高效。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值