502 lines
14 KiB
C++
502 lines
14 KiB
C++
|
#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
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|