EmbHMI/machine/tcpclient.cpp
2024-02-06 14:27:07 +08:00

502 lines
14 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "tcpclient.h"
#include <QSettings>
#include <QApplication>
#include <QAbstractSocket>
TcpClient::TcpClient(QObject *parent) :
QObject(parent),
m_pClientSocket(NULL),
m_pConnectCheckTimer(NULL),
m_connected(0),
m_pConnectDetectThread(NULL),
m_pConnectDetect(NULL),
m_detect(0),
m_localip(DEF_LOCAL_IP),
m_localport(DEF_LOCAL_PORT),
m_serverip(DEF_SERVER_IP),
m_serverport(DEF_SERVER_PORT)
{
m_pClientSocket = new QBindTcpSocket(this);
m_pClientSocket->setSocketOption(QAbstractSocket::KeepAliveOption, 1);
connect(m_pClientSocket, SIGNAL(readyRead()), this, SLOT(receiveServerData()));
connect(m_pClientSocket, SIGNAL(error(QAbstractSocket::SocketError)),
this, SLOT(displaySocketError(QAbstractSocket::SocketError)));
// connect(m_pClientSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(netStateChanged(QAbstractSocket::SocketState)));
m_pConnectCheckTimer = new QTimer(this);
connect(m_pConnectCheckTimer, SIGNAL(timeout()), this, SLOT(connectCheck()));
m_pConnectDetectThread = new QThread();
}
TcpClient::~TcpClient()
{
m_pConnectCheckTimer->stop();
delete m_pConnectCheckTimer;
m_pClientSocket->disconnectFromHost();
m_pClientSocket->waitForDisconnected();
m_pClientSocket->close();
delete m_pClientSocket;
if (m_connected != 0)
{
m_pConnectDetectThread->quit();
m_pConnectDetectThread->wait();
}
delete m_pConnectDetectThread;
}
void TcpClient::setConfigFileName(QString configfilename)
{
m_configFileName = configfilename;
}
void TcpClient::connectToServer()
{
if (m_pClientSocket == NULL)
{
qDebug() << "m_pClientSocket not alloc";
return;
}
if (m_connected == 0)
{
loadIpAndPort();
if (m_pConnectDetect == NULL)
{
m_pConnectDetect = new TcpConnectDetect;
}
qDebug() << "ConnectToServer";
qDebug() << "localip=" << m_localip << "localport=" << m_localport;
qDebug() << "serverip=" << m_serverip << "serverport=" << m_serverport;
m_pConnectDetect->setIpAndPort(m_localip, m_localport, m_serverip, m_serverport);
m_pConnectDetect->moveToThread(m_pConnectDetectThread);
connect(this, SIGNAL(siDetectHost()), m_pConnectDetect, SLOT(connectDetect()), Qt::QueuedConnection);
connect(m_pConnectDetect, SIGNAL(siConnectSta(int)), this, SLOT(detectStatus(int)), Qt::QueuedConnection);
// 20191226由于检测线程会造成网络重连所以将检测线程注释 lft
/*
connect(m_pConnectDetectThread, SIGNAL(started()), m_pConnectDetect, SLOT(detectStart()) );
connect(m_pConnectDetectThread, SIGNAL(finished()), m_pConnectDetect, SLOT(deleteLater()) ); // 退出删除对象
m_pConnectDetectThread->start(); // 启动线程
*/
m_pConnectCheckTimer->start(1000);
m_connected = 1;
m_detect = 1;
}
}
void TcpClient::disConnectFromServer()
{
if (m_connected != 0)
{
m_pConnectCheckTimer->stop();
if (m_pClientSocket != NULL)
{
m_pClientSocket->disconnectFromHost();
m_pClientSocket->waitForDisconnected();
m_pClientSocket->close();
}
m_pConnectDetectThread->quit();
m_pConnectDetectThread->wait();
m_connected = 0;
m_detect = 0;
}
}
void TcpClient::loadIpAndPort()
{
if (!m_configFileName.isEmpty())
{
// 机器的IP和端口 和 连接机器的本地IP和端口
QSettings configIni(m_configFileName, QSettings::IniFormat);
QString serverip, localip;
quint16 serverport, localport;
serverip = configIni.value("server/ip", QVariant("192.168.16.253")).toString();
serverport = configIni.value("server/port", QVariant(5000)).toInt();
localip = configIni.value("local/ip", QVariant("192.168.16.41")).toString();
localport = configIni.value("local/port", 5001).toInt();
// 回写参数
configIni.setValue("server/ip", serverip);
configIni.setValue("server/port", serverport);
configIni.setValue("local/ip", localip);
configIni.setValue("local/port", localport);
m_localip = localip;
m_localport = localport;
m_serverip = serverip;
m_serverport = serverport;
}
}
// 发送数据的槽
void TcpClient::slotSendData(QByteArray dat)
{
if (m_pClientSocket != NULL)
{
m_pClientSocket->write(dat);
}
}
// 自动检测连接
void TcpClient::connectCheck()
{
if (m_pClientSocket == NULL)
{
qDebug() << "Socket is not alloced";
return;
}
// qDebug() << "check client connect";
if (m_connected == 1)
{
if (m_localip.isEmpty() == false)
{
m_pClientSocket->bindAddrAndPort(m_localip, m_localport);
}
m_pClientSocket->abort();
m_pClientSocket->setSocketOption(QAbstractSocket::LowDelayOption, 1);
m_pClientSocket->connectToHost(m_serverip, m_serverport);
int rslt = m_pClientSocket->waitForConnected(2000);
if (rslt == 0)
{
}
/*
qDebug("bind connect and waitForConnected 2000, rslt=%d", rslt);
qDebug() << "localip=" << m_localip << "localport=" << m_localport;
qDebug() << "serverip=" << m_serverip << "serverport=" << m_serverport;
*/
m_connected = 2;
}
else if (m_connected != 0)
{
switch(m_pClientSocket->state())
{
case QAbstractSocket::ConnectedState:
{
if (m_connected != 3)
{
/*
qDebug() << "net State is Connected";
qDebug() << "localip=" << m_localip << "localport=" << m_localport;
*/
m_connected = 3; // 检测连接状态
}
break;
}
case QAbstractSocket::ConnectingState:
{
if (m_connected != 2)
{
qDebug() << "net State is Connecting";
// qDebug() << "localip=" << m_localip << "localport=" << m_localport;
}
m_connected = 2;
break;
}
case QAbstractSocket::UnconnectedState:
{
if (m_connected != 1)
{
// qDebug() << "net State is unconnected";
// qDebug() << "localip=" << m_localip << "localport=" << m_localport;
}
m_connected = 1;
break;
}
default:
{
/*
QAbstractSocket::HostLookupState
QAbstractSocket::BoundState
QAbstractSocket::ListeningState
QAbstractSocket::ClosingState
*/
{
qDebug("net State is %d\r\n", m_pClientSocket->state());
qDebug() << "localip=" << m_localip << "localport=" << m_localport;
qDebug() << "serverip=" << m_serverip << "serverport=" << m_serverport;
}
m_connected = 1;
}
}
}
else
{
}
if (m_connected == 3) // 已连接
{
if (m_detect == 1)
{
// qDebug() << "Machine " << QThread::currentThread();
m_detect = 0;
emit(siDetectHost());
// qDebug() << "after send SiDetectHost ";
}
}
emit (siConnectSta(m_connected)); // 网络连接信号
}
void TcpClient::detectStatus(int sta)
{
// qDebug("host detect sta=%d", sta);
m_detect = 1;
if (sta == 1) // 网络已断开
{
qDebug("disconnect ClientSocket by detect");
m_pClientSocket->disconnectFromHost();
// m_pClientSocket->waitForDisconnected();
m_pClientSocket->close();
m_connected = 1;
}
else if (sta == 2) // 网络连接还在
{
}
else
{
}
}
void TcpClient::receiveServerData()
{
if (m_pClientSocket != NULL)
{
QByteArray tmpDat;
tmpDat = m_pClientSocket->readAll(); // 读取
// qDebug("ReceiveServerData, size = %d", tmpDat.size());
// PrintAsHex(&tmpDat);
emit(siReceiveData(tmpDat)); // 发送收到数据信号
}
}
void TcpClient::displaySocketError(QAbstractSocket::SocketError err)
{
QString errinfo;
errinfo.sprintf("Err: code=%d, errorString=", err);
errinfo += m_pClientSocket->errorString();
// qDebug() << errinfo;
emit(siConnectErr(errinfo)); // 网络错误信息
}
void TcpClient::netStateChanged(QAbstractSocket::SocketState sta)
{
switch (sta)
{
/*
case UnconnectedState:
case HostLookupState:
case ConnectingState:
case ConnectedState:
case BoundState:
case ListeningState:
case ClosingStat:
*/
default:
break;
}
}
void TcpClient::hostFound()
{
qDebug("found host");
}
#if(0)
//-------------------------------------------------------
TcpConnectDetect::TcpConnectDetect(QObject *parent) :
QObject(parent),
m_pDetectSocket(NULL),
m_localip(DEF_LOCAL_IP),
m_localport(DEF_LOCAL_PORT),
m_serverip(DEF_SERVER_IP),
m_serverport(DEF_SERVER_PORT)
{
}
TcpConnectDetect::~TcpConnectDetect()
{
if (m_pDetectSocket == NULL)
{
m_pDetectSocket->disconnectFromHost();
m_pDetectSocket->waitForDisconnected();
m_pDetectSocket->close();
delete m_pDetectSocket;
}
}
void TcpConnectDetect::detectStart()
{
qDebug("TcpConnectDetect start");
if (m_pDetectSocket == NULL)
{
m_pDetectSocket = new QBindTcpSocket;
}
}
int TcpConnectDetect::connectDetect()
{
int connectsta = 0;
int rslt;
// qDebug() << "TcpConnectDetect " << QThread::currentThread();
if (m_pDetectSocket == NULL)
{
return 0;
}
if (m_localip.isEmpty() == false)
{
m_pDetectSocket->bindAddrAndPort(m_localip, m_localport);
}
m_pDetectSocket->abort();
m_pDetectSocket->setSocketOption(QAbstractSocket::LowDelayOption, 1);
m_pDetectSocket->connectToHost(m_serverip, m_serverport);
do
{
rslt = m_pDetectSocket->waitForConnected(4000); // 等待连接
qDebug("bind Detect connect rslt=%d", rslt);
qDebug() << "localip=" << m_localip << "localport=" << m_localport;
qDebug() << "serverip=" << m_serverip << "serverport=" << m_serverport;
switch(m_pDetectSocket->state())
{
case QAbstractSocket::ConnectedState:
{
// 如果连接上,说明 m_pClientSocket 连接已经无效, 需要断开重新连接
// 先断开测试连接
m_pDetectSocket->disconnectFromHost();
m_pDetectSocket->waitForDisconnected();
connectsta = 1;
// 发送断开主连接的信号
qDebug() << "detect is Connected, disconnect all";
break;
}
case QAbstractSocket::UnconnectedState:
{
// qDebug() << "detect is Unconnected err=" << m_pDetectSocket->error() << ", info:" << m_pDetectSocket->errorString();
switch (m_pDetectSocket->error())
{
case QAbstractSocket::SocketTimeoutError: // 连接超时,说明已经断开
case QAbstractSocket::NetworkError: // 网络错误, 主机不可连接, 可能已经断开
{
qDebug() << "detect is timout, disconnect all";
connectsta = 1;
// 发送断开主连接的信号
break;
}
case QAbstractSocket::ConnectionRefusedError: // 拒绝连接, 说明连接还在
{
connectsta = 2;
// qDebug() << "Connection Refused, old connect is alive";
break;
}
/*
case QAbstractSocket::RemoteHostClosedError:
case QAbstractSocket::HostNotFoundError:
case QAbstractSocket::SocketAccessError:
case QAbstractSocket::SocketResourceError:
case QAbstractSocket::SocketTimeoutError:
case QAbstractSocket::DatagramTooLargeError:
case QAbstractSocket::AddressInUseError:
case QAbstractSocket::SocketAddressNotAvailableError:
case QAbstractSocket::UnsupportedSocketOperationError:
case QAbstractSocket::UnfinishedSocketOperationError:
case QAbstractSocket::ProxyAuthenticationRequiredError:
case QAbstractSocket::SslHandshakeFailedError:
case QAbstractSocket::ProxyConnectionRefusedError:
case QAbstractSocket::ProxyConnectionClosedError:
case QAbstractSocket::ProxyConnectionTimeoutError:
case QAbstractSocket::ProxyNotFoundError:
case QAbstractSocket::ProxyProtocolError:
case QAbstractSocket::UnknownSocketError:
*/
default:
{
// 继续检测
connectsta = 2;
qDebug() << " retry";
break;
}
} // 错误处理结束
}
case QAbstractSocket::ConnectingState:
{
// qDebug() << "detect is Connecting";
// qDebug() << "localip=" << m_localip << "localport=" << m_localport;
// 继续等待
break;
}
case QAbstractSocket::HostLookupState:
case QAbstractSocket::BoundState:
case QAbstractSocket::ListeningState:
case QAbstractSocket::ClosingState:
default:
{
// 继续等待
qDebug("detect sta is %d\r\n", m_pDetectSocket->state());
break;
}
}
if (connectsta != 0)
{
break;
}
}while(1);
m_pDetectSocket->close();
// 发送本次测试连接的状态信号
emit(siConnectSta(connectsta));
return connectsta;
}
void TcpConnectDetect::setIpAndPort(QString localip, quint16 localport, QString serverip, quint16 serverport)
{
m_localip = localip;
m_localport = localport;
m_serverip = serverip;
m_serverport = serverport;
}
#endif