QT tcp客户端线程

头文件CSerialThread.h

#pragma once

#include <QThread>
#include <QTcpSocket>
#include <QByteArray>
class CSerialThread : public QThread
{
    Q_OBJECT

public:
    CSerialThread(QObject *parent = nullptr);
    ~CSerialThread();
    void Stop();
protected:
    void run() override;
private slots:
    void OnReadyRead();
    void OnThreadFinished();
private:
    void SendToServer(const QByteArray& res);

 private:
    QString id;
    quint16 port;
    QTcpSocket* m_Socket;
    QByteArray m_buffer;
    int m_nPackSize;
};

实现CSerialThread.cpp

#include "CSerialThread.h"
#include "CCommandInterface.h"
#include "CMutilQueues.h"
#include <QDebug>
#include "CGoogleLog.h"
#include <QDataStream>
#include "CConfig.h"
CSerialThread::CSerialThread(QObject *parent)
    : QThread(parent)
{
    this->moveToThread(this);
    connect(this, &QThread::finished, this, &CSerialThread::OnThreadFinished);
    m_Socket = nullptr;
    id = QString::fromStdString(CCfgInstance::Get()->GetValue("server_ip"));
    port = std::stoi(CCfgInstance::Get()->GetValue("server_port"));
    m_nPackSize = std::stoi(CCfgInstance::Get()->GetValue("pack_size"));
}

CSerialThread::~CSerialThread()
{
}

void CSerialThread::Stop()
{
    exit();
    wait();
}

void CSerialThread::run()
{
    m_Socket = new QTcpSocket(this);
    m_Socket->connectToHost(id, port);
    if (m_Socket->waitForConnected(30000))
    {
        connect(m_Socket, &QTcpSocket::readyRead, this, &CSerialThread::OnReadyRead, Qt::QueuedConnection);
        LOG(INFO) << "服务器连接成功";
        SendToServer("Connected Server");
        exec();
    }
    else
    {
        if (m_Socket->isOpen())
        {
            m_Socket->close();
        }
        return;
    }
}
void CSerialThread::SendToServer(const QByteArray& res)
{
    QByteArray byt;
    QDataStream data_stream(&byt, QIODevice::WriteOnly);
    data_stream.setByteOrder(QDataStream::BigEndian);
    data_stream << res;

    m_Socket->write(byt);
    m_Socket->flush();
}

void CSerialThread::OnReadyRead()
{
    if (m_Socket->bytesAvailable() <= 0)
    {
        return;
    }

    //临时获得从缓存区取出来的数据,但是不确定每次取出来的是多少。
    QByteArray buffer;

    //如果是信号readyRead触发的,使用readAll时会一次把这一次可用的数据全总读取出来
    buffer = m_Socket->readAll();
    uint uMessLen = buffer.size();
    LOG(INFO) << "Mess Len: " << uMessLen;

    //上次缓存加上这次数据
    m_buffer.append(buffer);
    ushort uTypeId;


    //分包发送
    int nTotalLen = (int)m_buffer.size();
    while (nTotalLen)
    {
        QDataStream packet(m_buffer);
        packet.setByteOrder(QDataStream::BigEndian);

        if (nTotalLen < m_nPackSize)//不够发送数据
        {
            break;
        }

		//读取一包数据
        QByteArray bf;
        bf.resize(m_nPackSize);
        packet.readRawData(bf.data(), m_nPackSize);

        //将包发送给处理队列,(这块根据自己需求来写。)
        std::shared_ptr<CCommandInterface> pCommand(new CCommandSerial(bf));
        shared_ptr<CCommandSerial> ptrSeral = std::dynamic_pointer_cast<CCommandSerial>(pCommand);
        if (ptrSeral == nullptr)
        {
            LOG(INFO) << "dynamic_pointer_cast error";
            continue;
        }
        ptrSeral->ParseCommand();
        CMutilQueues::PutData(EQueueId::SERIAL, pCommand);

        //缓存多余的数据
        buffer = m_buffer.right(nTotalLen - uMessLen);
        //更新长度
        nTotalLen = buffer.size();
        //更新多余数据
        m_buffer = buffer;
    }
}

void CSerialThread::OnThreadFinished()
{
    LOG(INFO) << "OnThreadFinished";
}
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Qt线程TCP客户端是一种可以在Qt应用程序中使用的多线程网络通信工具。 在使用Qt线程TCP客户端之前,首先需要创建一个TCP Socket对象,并使用connectToHost方法连接到服务器。连接成功后,可以使用write方法发送数据到服务器。 为了实现多线程,可以使用Qt中的QThread类。首先,创建一个继承自QThread的自定义线程类,并重写run方法。在run方法中,可以编写与服务器进行通信的代码。 为了在多个线程之间共享数据,可以使用Qt中的信号和槽机制。可以在客户端线程类中定义信号,并在需要发送数据时发射信号。然后,可以将信号与服务器连接的槽函数进行连接,以便在接收到信号时执行相应的操作。 在客户端线程类中还可以使用信号和槽机制实现与主线程的通信。例如,可以在主线程中定义一个槽函数,用于接收从客户端线程发射的信号,并更新界面或执行其他相关操作。 为了确保多线程的安全性,需要采取适当的线程同步措施。可以使用Qt中的Mutex或其他同步原语来保护共享数据,以避免竞争条件和数据损坏。 使用Qt线程TCP客户端时,需要仔细处理异常情况,例如连接中断或网络错误。可以在连接断开时发射信号,以便在主线程中进行错误处理或重新连接。 总而言之,Qt线程TCP客户端是一种在Qt应用程序中实现多线程网络通信的方法。通过合理的设计和使用线程同步机制,可以实现高效的并发通信,并确保数据的安全性和可靠性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值