头文件tcpclient.h
#ifndef TCPCLIENT_H
#define TCPCLIENT_H
#include
#include
#include
#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
#include
#include
#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
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
#include
#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
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