Qt TCP Client

头文件tcpclient.h

#ifndef TCPCLIENT_H
#define TCPCLIENT_H

#include <QObject>
#include <QTcpSocket>
#include <QDebug>
#include "enthernetdataparsing.h"
#include "tf500enthernetdataparsing.h"

class TCPClient : public QObject
{
    Q_OBJECT
public:
    explicit TCPClient(QObject *parent = 0);
    
signals:
    void reConnect();
    
public slots:
    void slot_connectServer(QString serverIP, quint16 port);

    void slot_reConnectServer();

private slots:
    void processError(QAbstractSocket::SocketError socketError);

    void readData();

    qint64 writeData(const char * data, qint64 len);

    void hostFound();

    void connected();

private:
    QTcpSocket *tcpSocket;

    QString serverIP;

    quint16 port;

    char *recvBuf;

    EnthernetDataParsing *enthernetDataParsing;

private:
    void reConnectServer();

    void allocMemory();

    void disconnectFromServer();

public:
    void connectServer(QString serverIP, quint16 port);
    
};

#endif // TCPCLIENT_H

.cpp

#include <QThread>
#include <QtEndian>
#include <syslog.h>
#include "tcpclient.h"
#include "printfhex.h"

TCPClient::TCPClient(QObject *parent) :
    QObject(parent)
{
    tcpSocket = new QTcpSocket(this);
    tcpSocket->setReadBufferSize(32 * 1024);

    enthernetDataParsing = new TF500EnthernetDataParsing();

    recvBuf = NULL;
    allocMemory();

    connect(enthernetDataParsing, SIGNAL(writeData(const char*,qint64)),
            this, SLOT(writeData(const char*,qint64)));

    connect(tcpSocket, SIGNAL(error(QAbstractSocket::SocketError)),
            this, SLOT(processError(QAbstractSocket::SocketError)));

    connect(tcpSocket, SIGNAL(hostFound()), this, SLOT(hostFound()));

    connect(tcpSocket, SIGNAL(connected()), this, SLOT(connected()));

    connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(readData()));

    connect(tcpSocket, SIGNAL(disconnected()), this, SLOT(slot_reConnectServer()));

    connect(this, SIGNAL(reConnect()), this, SLOT(slot_reConnectServer()));
}

void TCPClient::allocMemory()
{
    if(!recvBuf){
        recvBuf = new char[MAX_RECVBUF_LEN];
        memset(recvBuf, 0, MAX_RECVBUF_LEN);
    }

    if(!recvBuf)
    {
        qDebug("Alloc Memory error in File:%s Line:%d.", __FILE__, __LINE__);
        syslog(LOG_ERR | LOG_USER, "Alloc Memory error in File:%s Line:%d.", __FILE__, __LINE__);
    }
}

void TCPClient::disconnectFromServer()
{
    tcpSocket->disconnectFromHost();
    bool ret = tcpSocket->waitForDisconnected(5000);
    qDebug() << "disconnectFromHost: " << ret;
}

void TCPClient::slot_connectServer(QString serverIP, quint16 port)
{
    connectServer(serverIP, port);
}

void TCPClient::slot_reConnectServer()
{
    reConnectServer();
}

void TCPClient::processError(QAbstractSocket::SocketError socketError)
{
    switch(socketError){
    case QAbstractSocket::ConnectionRefusedError:
        qDebug() <<  tr("The connection was refused by the peer (or timed out).");
        emit reConnect();
        break;
    case QAbstractSocket::RemoteHostClosedError:
        qDebug() <<  tr("Remote host closed the connection.");
        break;
    case QAbstractSocket::HostNotFoundError:
        qDebug() <<  tr("The host was not found. Please check the host name and port settings.");
        break;
//    case QAbstractSocket::SocketAccessError:
//        break;
//    case QAbstractSocket::SocketResourceError:
//        break;
//    case QAbstractSocket::SocketTimeoutError:
//        break;
//    case QAbstractSocket::DatagramTooLargeError:
//        break;
    case QAbstractSocket::NetworkError: //e.g., the network cable was accidentally plugged out
        qDebug() <<  tr("An error occurred with the network.");
        emit reConnect();
        break;
//    case QAbstractSocket::UnsupportedSocketOperationError:
//        break;
    default:
        qDebug() << tr("The following error occurred: %1.").arg(tcpSocket->errorString());
        break;
    }
}

void TCPClient::readData()
{
    int recvLen = 0, onceRecvLen = 0;

    while(1){
        if(recvLen < FRAME_HEAD_LEN){
            onceRecvLen = tcpSocket->read(recvBuf + recvLen, FRAME_HEAD_LEN - recvLen);
            if(onceRecvLen == -1){
                tcpSocket->close();
                break;
            }
            recvLen += onceRecvLen;
        }
        else{
            int frameLen = 0;
            memcpy(&frameLen, recvBuf + START_FRAME_LEN, 4);
            frameLen = qToBigEndian(frameLen);

            if(recvLen < frameLen){
                onceRecvLen = tcpSocket->read(recvBuf + recvLen, frameLen - recvLen);
                if(onceRecvLen == -1){
                    tcpSocket->close();
                    break;
                }
                recvLen += onceRecvLen;
            }
            else if(recvLen == frameLen){
                PrintfHex printfHex;
                printf("Receive data:");
                printfHex.printfHex(recvBuf, FRAME_HEAD_LEN, true);
                //process
                enthernetDataParsing->parseData(recvBuf, recvLen);
                break;
            }
            else{
                tcpSocket->readAll();
                break;
            }
        }
    }

    qDebug() << "readBytes:" << recvLen;
    qDebug() << "readData in thread:" << QThread::currentThread();
}

qint64 TCPClient::writeData(const char *data, qint64 len)
{
    qDebug() << "write data in TCPClient.";

    qint64 onceWriteLen = 0, sendLen = 0;

//    onceWriteLen = tcpSocket->write(data + onceWriteLen, len - onceWriteLen);
}

void TCPClient::hostFound()
{
    qDebug() << "Host found success.";
}

void TCPClient::connected()
{
    qDebug() << QString("Connect to ip:%1 port:%2 success.").arg(serverIP).arg(port);
}

void TCPClient::connectServer(QString serverIP, quint16 port)
{
    this->serverIP = serverIP;
    this->port = port;
    tcpSocket->connectToHost(serverIP, port);
    tcpSocket->waitForConnected(5000);
}

void TCPClient::reConnectServer()
{
    sleep(2);
    tcpSocket->connectToHost(serverIP, port);
    tcpSocket->waitForConnected(5000);
}

Printfhex是一个打印char数组的类,以16进制打印。

EnthernetDataParsing是一个纯虚类,解析收到的数据,源码如下:

#ifndef ENTHERNETDATAPARSING_H
#define ENTHERNETDATAPARSING_H

#include <QObject>

class EnthernetDataParsing : public QObject
{
    Q_OBJECT
public:
    explicit EnthernetDataParsing(QObject *parent = 0);
    
signals:
    void writeData(const char * data, qint64 len);
    
public slots:

public:
    virtual int parseData(char *data, qint64 len) = 0;
    
};

#endif // ENTHERNETDATAPARSING_H

TF500EnthernetDataParsing继承自EnthernetDataParsing,是按照具体协议解析数据的类。

解析出命令后调用完成对应业务的类,执行完成后发送执行结果。

一般会把TCPClient放到线程中执行:

#include <QtCore/QCoreApplication>
#include <QThread>
#include "tcpclient.h"
#include "tcpclientop.h"

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

    TCPClient tcpClient;
    TCPClientOP tcpClientOP;

    QThread thread;
    tcpClient.moveToThread(&thread);
    QObject::connect(&tcpClientOP, SIGNAL(connectServer(QString,quint16)),
                     &tcpClient, SLOT(slot_connectServer(QString,quint16)));
    thread.start();

    tcpClientOP.startConnect("10.0.10.55", 11866);

    qDebug() << "main thread:" << QThread::currentThread();

    return a.exec();
}

TCPClientOP

#ifndef TCPCLIENTOP_H
#define TCPCLIENTOP_H

#include <QObject>

class TCPClientOP : public QObject
{
    Q_OBJECT
public:
    explicit TCPClientOP(QObject *parent = 0):QObject(parent){};
    
signals:
    void connectServer(QString serverIP, quint16 port);
    
public slots:

public:
    void startConnect(QString serverIP, quint16 port)
    {
        emit connectServer(serverIP, port);
    }
    
};

#endif // TCPCLIENTOP_H

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值