IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> 【Qt】基于QTcpSocket的TCP客户端实现 -> 正文阅读

[网络协议]【Qt】基于QTcpSocket的TCP客户端实现

客户端通信流程:
①创建套接字:new QTcpSocket。
②连接服务器:可以使用QTcpSocket类的connectToHost()函数来连接服务器。
③向服务器发送或者接受数据。

下面代码一共有三个文件,分别是main.cpp、atcpclient.h、atcpclient.cpp.

其中main.cpp是用于测试ATcpClient的。封装好了的ATcpClient运行于线程中,可用于其他小项目中。

// atcpclient.h

#ifndef ATCPCLIENT_H
#define ATCPCLIENT_H

#include <QObject>
#include <QTcpSocket>
#include <QThread>
#include <QTimer>

class ATcpClient : public QObject
{
    Q_OBJECT
public:
    ATcpClient(QString sServerIp, int nPort, QObject *parent = 0);
    virtual ~ATcpClient();

    int  sendData(QByteArray baData);
    void setReConnectInterval(int nMSec);

protected:
    virtual void initInThread();
    virtual void deinitInThread();

    virtual void doReConnect();
    virtual void setConnectStatus(bool bIsConnect);

    virtual int doSendDataImp(QByteArray baData);
    virtual int doRecvDataImp(const QByteArray &baRecvData);

signals:
    void sigSendData(QByteArray baData);
    void sigOnDeinit();

private slots:
    void sltSendData(QByteArray baData);
    void sltReadyRead();

    void sltOnConnected();
    void sltOnDisonnected();
    void sltOnError(QAbstractSocket::SocketError nErrCode);
    void sltOnStateChanged(QAbstractSocket::SocketState nSocketState);

private:
    QString m_sServerIp;
    int m_nPort;
    int m_nInterval;
    bool m_bConnected{false};

    QThread* m_pThread{nullptr};
    QTimer* m_pTimer{nullptr};
    QTcpSocket* m_pSocketClient{nullptr};
};

#endif // ATCPCLIENT_H
// atcpclient.cpp

#include "atcpclient.h"
#include <QHostAddress>
#include <QTimer>
#include <QEventLoop>

ATcpClient::ATcpClient(QString sServerIp, int nPort, QObject *parent)
    : m_sServerIp(sServerIp)
    , m_nPort(nPort)
    , m_nInterval(50)
    , QObject(parent)
{
    qDebug() << QString::fromLocal8Bit("ATcpClient::ATcpClient(%1,%2)").arg(m_sServerIp).arg(m_nPort);

    m_pThread = new QThread();
    m_pThread->setObjectName("TcpClient");
    m_pThread->start();
    this->moveToThread(m_pThread);

    //不要直接调用initInThread(),否则并非在线程内初始化
    QTimer::singleShot(0,this, &ATcpClient::initInThread);
}

ATcpClient::~ATcpClient()
{
    qDebug() << "ATcpClient::~ATcpClient()";

    //两种错误的反初始化方法,会导致无法kill掉QTimer.
    //deinitInThread();
    //QTimer::singleShot(0, this, &ATcpClient::deinitInThread);

    //正确的反初始化方法: 在线程内反初始化
    QEventLoop loop;
    connect(this, SIGNAL(sigOnDeinit()), &loop, SLOT(quit()));
    QTimer::singleShot(0, this, &ATcpClient::deinitInThread);
    loop.exec();

    if (nullptr != m_pThread)
    {
        m_pThread->quit();
        m_pThread->wait();
        m_pThread->deleteLater();
    }
}

int ATcpClient::sendData(QByteArray baData)
{
    emit sigSendData(baData);
    return baData.length();
}

void ATcpClient::setReConnectInterval(int nMSec)
{
    m_nInterval = nMSec;
}

void ATcpClient::initInThread()
{
    if(nullptr == m_pTimer)
    {
        m_pTimer = new QTimer(this);
        connect(m_pTimer, &QTimer::timeout, this, &ATcpClient::doReConnect);
    }
    m_pTimer->start(m_nInterval);

    if(nullptr == m_pSocketClient)
    {
        m_pSocketClient = new QTcpSocket(this);
        connect(m_pSocketClient, SIGNAL(connected()), this, SLOT(sltOnConnected()));
        connect(m_pSocketClient, SIGNAL(disconnected()), this, SLOT(sltOnDisonnected()));
        connect(m_pSocketClient, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(sltOnStateChanged(QAbstractSocket::SocketState)));
        connect(m_pSocketClient, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(sltOnError(QAbstractSocket::SocketError)));
        connect(m_pSocketClient, SIGNAL(readyRead()), this, SLOT(sltReadyRead()));

        m_pSocketClient->setSocketOption(QAbstractSocket::LowDelayOption, 1);
        m_pSocketClient->setSocketOption(QAbstractSocket::KeepAliveOption, 1);
        m_pSocketClient->connectToHost(QHostAddress(m_sServerIp), m_nPort);
    }

    connect(this, SIGNAL(sigSendData(QByteArray)), this, SLOT(sltSendData(QByteArray)));
}

void ATcpClient::deinitInThread()
{
    if(nullptr != m_pTimer)
    {
        m_pTimer->stop();
        delete m_pTimer;
        m_pTimer = nullptr;
    }

    if(nullptr != m_pSocketClient)
    {
	m_pSocketClient->disconnectFromHost();
	delete m_pSocketClient;
	m_pSocketClient = NULL;
    }

    emit sigOnDeinit();
}

void ATcpClient::doReConnect()
{
    if(false == m_bConnected && nullptr != m_pSocketClient)
    {
        m_pSocketClient->disconnectFromHost();
        m_pSocketClient->connectToHost(QHostAddress(m_sServerIp), m_nPort);
    }
}

void ATcpClient::setConnectStatus(bool bIsConnect)
{
    if(m_bConnected != bIsConnect)
    {
        m_bConnected = bIsConnect;
    }
}

int ATcpClient::doSendDataImp(QByteArray baData)
{
    if(nullptr == m_pSocketClient || false == m_bConnected)
    {
        qDebug() << "TcpClient socket not connect.";
        return -1;
    }

    int nWriteSize = m_pSocketClient->write(baData);
    if(m_pSocketClient->flush())
    {
        qDebug() << "[" << QString::fromLocal8Bit("%1:%2").arg(m_sServerIp).arg(m_nPort)
                 << "] Write["<< nWriteSize
                 <<"]:"<< QString::fromLocal8Bit(baData);
    }
    else
    {
        qDebug() << "[" << QString::fromLocal8Bit("%1:%2").arg(m_sServerIp).arg(m_nPort)
                 << "] Write Fail["<< nWriteSize
                 << "]:"<< QString::fromLocal8Bit(baData);
    }

    return nWriteSize;
}

int ATcpClient::doRecvDataImp(const QByteArray &baRecvData)
{
    qDebug() << "[" << QString::fromLocal8Bit("%1:%2").arg(m_sServerIp).arg(m_nPort)
             << "] Recv: " << QString::fromLocal8Bit(baRecvData);
}

void ATcpClient::sltSendData(QByteArray baData)
{
    doSendDataImp(baData);
}

void ATcpClient::sltReadyRead()
{
    QByteArray baRecv = m_pSocketClient->readAll();
    doRecvDataImp(baRecv);
}

void ATcpClient::sltOnConnected()
{
    setConnectStatus(true);
    qDebug() << "[" << QString::fromLocal8Bit("%1:%2").arg(m_sServerIp).arg(m_nPort)
             <<"] Connect success.";
}

void ATcpClient::sltOnDisonnected()
{
    setConnectStatus(false);
    qDebug() << "[" << QString::fromLocal8Bit("%1:%2").arg(m_sServerIp).arg(m_nPort)
             << "] Disconnect success.";
}

void ATcpClient::sltOnError(QAbstractSocket::SocketError nErrCode)
{
    qDebug() << "[" << QString::fromLocal8Bit("%1:%2").arg(m_sServerIp).arg(m_nPort)
             << "] socket error,code:" << nErrCode;
	m_pSocketClient->disconnectFromHost();
    setConnectStatus(false);
}

void ATcpClient::sltOnStateChanged(QAbstractSocket::SocketState nSocketState)
{
    qDebug() << "[" << QString::fromLocal8Bit("%1:%2").arg(m_sServerIp).arg(m_nPort)
             << "] socket state change:" << nSocketState;
}
// main.cpp-用于测试

#include <QCoreApplication>
#include "atcpclient.h"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    {
        ATcpClient tcpClient("127.0.0.1", 9999);

        for(int i=0; i<5; ++i)
        {
           QThread::sleep(1);
           tcpClient.sendData("aaaa");
        }
    }

    return a.exec();
}

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2021-07-14 23:16:55  更:2021-07-14 23:18:37 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/28 12:34:45-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码