上一篇QTcpSocket斷網重連地址:QTcpSocket斷網重連(一)
在第一篇中Linux下有一個潛在的bug,不會影響到客戶端,但是對服務器端會有一定影響,在服務器端物理斷網的情況下,會出現一旦服務器恢復網絡後客戶端斷網重連時,會出現服務器端有多個端口連接情況。但是客戶端這邊檢查只有一次連接,所以這個現在只能猜測出現bug原因。
通過這一篇中代碼的測試,有以下猜測:
- abort()-----------這個函數執行時,不會清除上一次連接端口,但是官方對這個函數的解釋是:終止當前連接並重置套接字。與disconnectFromHost()不同,此函數立即關閉套接字,丟棄寫緩衝區中的任何掛起數據。
- 服務器端物理斷網後,QTcpSocket本身是檢測不到斷網情況的,根據段時間後沒有連上,那麼開始不斷連接,連接信號發出去後,本地處於掛起狀態沒有銷燬掉,上一次連接信息繼續發出連接請求導致出現多個端口連接情況
下面通過代碼講解實現思路:
#ifndef TCPSOCKETCLIENT_H
#define TCPSOCKETCLIENT_H
#include <QObject>
#include <QTcpSocket>
#include <QTimer>
class TcpSocketClient : QObject
{
Q_OBJECT
public:
TcpSocketClient();
~TcpSocketClient();
void startConnect(const QString& strAddressIP, quint16 iPort);
private:
QTcpSocket *m_TcpSocket;
bool b_isConnectState;
QString m_strAddressIP;
quint16 m_iPort;
QTimer *m_timerConnect;
QTimer *m_timerSend;
private slots:
void onConnect();
void onDisConnect();
void onErrorString(QAbstractSocket::SocketError errorString);
void onRecvData();
void onSendData();
};
#endif // TCPSOCKETCLIENT_H
#include "tcpsocketclient.h"
#include <QDebug>
TcpSocketClient::TcpSocketClient()
: b_isConnectState(false)
, m_strAddressIP("127.0.0.1"), m_iPort(0)
{
m_TcpSocket = new QTcpSocket();
connect(m_TcpSocket, SIGNAL(connected()), this, SLOT(onConnect()));
connect(m_TcpSocket, SIGNAL(disconnected()) , this, SLOT(onDisConnect()));
connect(m_TcpSocket, SIGNAL(readyRead()), this, SLOT(onRecvData()));
connect(m_TcpSocket, SIGNAL(error(QAbstractSocket::SocketError)),
this, SLOT(onErrorString(QAbstractSocket::SocketError)), Qt::DirectConnection);
m_timerConnect = new QTimer();
connect(m_timerConnect, &QTimer::timeout, [=](){
if(b_isConnectState)
return;
if(m_TcpSocket->state() == QAbstractSocket::ConnectingState)
return;
m_TcpSocket->connectToHost(m_strAddressIP, m_iPort);
});
m_timerSend = new QTimer();
connect(m_timerSend, &QTimer::timeout, [=](){
onSendData();
});
}
TcpSocketClient::~TcpSocketClient()
{
m_TcpSocket->abort();
}
void TcpSocketClient::startConnect(const QString &strAddressIP, quint16 iPort)
{
m_strAddressIP = strAddressIP;
m_iPort = iPort;
m_timerConnect->start(1000);
}
void TcpSocketClient::onConnect()
{
b_isConnectState = true;
qDebug() << "onConnect";
m_timerConnect->stop();
m_timerSend->start(200);
}
void TcpSocketClient::onDisConnect()
{
b_isConnectState = false;
qDebug() << "onDisConnect";
m_timerConnect->start(1000);
m_timerSend->stop();
}
void TcpSocketClient::onErrorString(QAbstractSocket::SocketError errorString)
{
qDebug() << errorString;
}
void TcpSocketClient::onRecvData()
{
if(m_TcpSocket->state() != QAbstractSocket::ConnectedState)
return;
if(m_TcpSocket->bytesAvailable() < 0)
{
m_TcpSocket->disconnectFromHost();
m_TcpSocket->waitForDisconnected(3000);
}
while (m_TcpSocket->bytesAvailable() > 0)
{
QByteArray arrayData;
arrayData.resize((int)m_TcpSocket->bytesAvailable());
m_TcpSocket->read(arrayData.data(), arrayData.size());
QString str_tcp_receive = QString::fromLocal8Bit(arrayData);
qDebug() << str_tcp_receive;
}
}
void TcpSocketClient::onSendData()
{
if(m_TcpSocket->state() != QAbstractSocket::ConnectedState)
return;
QString strData = "123";
qint64 iSendDataLength = m_TcpSocket->write(strData.toUtf8().data(), strData.length());
if(!m_TcpSocket->flush() || iSendDataLength < 0)
{
m_TcpSocket->disconnectFromHost();
m_TcpSocket->waitForDisconnected(3000);
}
}
注意:
1、在主線程中使用要注意QTcpSocket
中的所有 wait****
函數,所有的這類函數都會導致阻塞主線程,使用時候需要注意
2、如果有斷不開的情況,一般是因爲onSendData
函數部分,一直在發送導致,可以主動觸發disconnected
信號
這是一個簡單示例,有需要的可以下載查看:https://download.csdn.net/download/bloke_come/12346214