200 lines
6.9 KiB
C++
200 lines
6.9 KiB
C++
#include "MyTcpClient.h"
|
||
#include <QDebug>
|
||
|
||
MyTcpClient* MyTcpClient::m_instance = nullptr;
|
||
|
||
MyTcpClient::MyTcpClient(QObject *parent) : QObject(parent), shouldReconnect(true) {
|
||
socket = new QTcpSocket(this);
|
||
|
||
connect(socket, &QTcpSocket::connected, this, &MyTcpClient::onConnected);
|
||
connect(socket, &QTcpSocket::readyRead, this, &MyTcpClient::onReadyRead);
|
||
connect(socket, &QTcpSocket::disconnected, this, &MyTcpClient::onDisconnected);
|
||
//connect(socket, &QTcpSocket::errorOccurred, this, &MyTcpClient::onErrorOccurred);
|
||
|
||
// 连接失败后,定时尝试重连
|
||
connect(&reconnectTimer, &QTimer::timeout, this, &MyTcpClient::onReconnect);
|
||
reconnectTimer.setInterval(5000); // 5秒重连一次
|
||
memset(header,0,sizeof(header));
|
||
int packge_len = 0;
|
||
}
|
||
|
||
MyTcpClient::~MyTcpClient() {
|
||
shouldReconnect = false;
|
||
if (socket) {
|
||
socket->disconnectFromHost();
|
||
socket->deleteLater();
|
||
}
|
||
}
|
||
MyTcpClient* MyTcpClient::instance()
|
||
{
|
||
if (!m_instance) {
|
||
m_instance = new MyTcpClient();
|
||
}
|
||
return m_instance;
|
||
}
|
||
void MyTcpClient::connectToServer(const QString &host, quint16 port) {
|
||
serverHost = host;
|
||
serverPort = port;
|
||
if (socket->state() == QAbstractSocket::ConnectedState) {
|
||
qDebug() << "Already connected!";
|
||
return;
|
||
}
|
||
qDebug() << "Connecting to" << host << ":" << port;
|
||
socket->connectToHost(host, port);
|
||
if (!socket->waitForConnected()) {
|
||
qDebug() << "Connection failed!";
|
||
return;
|
||
}
|
||
}
|
||
|
||
int MyTcpClient::sendData(char*data,qint64 len) {
|
||
|
||
qint64 bytesWritten = socket->write(data, len);
|
||
socket->waitForBytesWritten();
|
||
return bytesWritten;
|
||
}
|
||
void MyTcpClient::waitForRead() {
|
||
socket->waitForReadyRead();
|
||
}
|
||
void MyTcpClient::disconnectFromServer() {
|
||
shouldReconnect = false; // 停止自动重连
|
||
reconnectTimer.stop();
|
||
heartbeatTimer.stop();
|
||
socket->disconnectFromHost();
|
||
}
|
||
|
||
void MyTcpClient::onConnected() {
|
||
qDebug() << "Connected to server!";
|
||
emit connected();
|
||
|
||
reconnectTimer.stop(); // 连接成功,停止自动重连
|
||
heartbeatTimer.start(); // 开始发送心跳包
|
||
}
|
||
|
||
void MyTcpClient::onReadyRead() {
|
||
// while (socket->bytesAvailable() > 0) {
|
||
// if (m_waitingForHeader) {
|
||
// // 1. 先尝试读取头部(固定长度)
|
||
// if (socket->bytesAvailable() < 4) {
|
||
// continue; // 数据不够,等待下次触发
|
||
// }
|
||
|
||
// // 读取头部
|
||
// socket->read(reinterpret_cast<char*>(&header), 4);
|
||
|
||
// // 验证头部标识(0xAA55AA)
|
||
// if (header[0] != 0xAA ||
|
||
// header[1] != 0x55 ||
|
||
// header[2] != 0xAA) {
|
||
// qWarning() << "Invalid header! Disconnecting...";
|
||
// return;
|
||
// }
|
||
// char temp[10]={0};
|
||
// if(header[3] == kDownloadConfigFile){
|
||
|
||
// socket->read(reinterpret_cast<char*>(&temp), 6);
|
||
// memcpy((char*)&packge_len,temp + 2, 4);
|
||
// }else{
|
||
// QByteArray remain_data = socket->readAll();
|
||
// m_buffer.clear();
|
||
// m_buffer.append(reinterpret_cast<char*>(&header), 4); // 先存头部
|
||
// m_buffer.append(remain_data);
|
||
// emit dataReceived(m_buffer);
|
||
// break;
|
||
// }
|
||
|
||
// // 进入等待数据状态
|
||
// m_waitingForHeader = false;
|
||
// m_buffer.clear();
|
||
// m_buffer.append(reinterpret_cast<char*>(&header), 4); // 先存头部
|
||
// m_buffer.append(reinterpret_cast<char*>(&temp), 6); // 先存头部
|
||
// } else {
|
||
// // 2. 根据头部的 len 读取剩余数据
|
||
// qint64 remainingBytes = packge_len - (m_buffer.size() - 10);
|
||
|
||
// if (remainingBytes <= 0) {
|
||
// // 数据已经完整,触发信号
|
||
// emit dataReceived(m_buffer);
|
||
// m_waitingForHeader = true; // 重置状态,准备接收下一个包
|
||
// break; // 继续处理缓冲区可能的下一个包
|
||
// }
|
||
|
||
// // 读取剩余数据(不超过 remainingBytes)
|
||
// QByteArray newData = socket->read(remainingBytes);
|
||
// qDebug() << "Read" << newData.size() << "bytes";
|
||
// m_buffer.append(newData);
|
||
|
||
// // 检查是否已经读完
|
||
// if (m_buffer.size() - 10 >= packge_len) {
|
||
// qDebug() << "m_buffer" << m_buffer.size() << "bytes";
|
||
// emit dataReceived(m_buffer);
|
||
// m_waitingForHeader = true; // 准备接收下一个包
|
||
// break;
|
||
// }
|
||
// }
|
||
// }
|
||
m_buffer.append(socket->readAll());
|
||
|
||
while (true) {
|
||
if (m_buffer.size() < sizeof(BaseHeader)) return;
|
||
|
||
const BaseHeader *base = reinterpret_cast<const BaseHeader *>(m_buffer.constData());
|
||
if (!(base->head[0] == 0xAA && base->head[1] == 0x55 && base->head[2] == 0xAA)) {
|
||
m_buffer.remove(0, 1);
|
||
continue;
|
||
}
|
||
|
||
uint8_t cmd = base->cmd;
|
||
|
||
if (cmd == kDownloadConfigFile) {
|
||
if (m_buffer.size() < sizeof(BaseHeader) + sizeof(LargeHeaderExtra))
|
||
return; // 等待更多数据
|
||
|
||
const LargeHeaderExtra *extra = reinterpret_cast<const LargeHeaderExtra *>(
|
||
m_buffer.constData() + sizeof(BaseHeader));
|
||
int payloadLen = extra->len;
|
||
if (payloadLen <= 0 || payloadLen > 1024 * 1024) {
|
||
qWarning() << "Detected abnormal payload length:" << payloadLen;
|
||
m_buffer.remove(0, sizeof(BaseHeader)); // 丢弃当前包头
|
||
continue;
|
||
}
|
||
int totalLen = sizeof(BaseHeader) + sizeof(LargeHeaderExtra) + extra->len;
|
||
if (m_buffer.size() < totalLen)
|
||
return; // 等待完整数据到达
|
||
|
||
QByteArray payload = m_buffer.mid(sizeof(BaseHeader) + sizeof(LargeHeaderExtra), extra->len);
|
||
emit dataReceived( m_buffer);
|
||
m_buffer.remove(0, totalLen);
|
||
} else {
|
||
QByteArray fullData = m_buffer;
|
||
emit dataReceived(fullData);
|
||
m_buffer.clear();
|
||
return; // 等待下一批数据
|
||
}
|
||
}
|
||
}
|
||
|
||
void MyTcpClient::onDisconnected() {
|
||
qDebug() << "Disconnected from server!";
|
||
emit disconnected();
|
||
|
||
if (shouldReconnect) {
|
||
qDebug() << "Attempting to reconnect in 5 seconds...";
|
||
reconnectTimer.start(); // 触发自动重连
|
||
heartbeatTimer.stop(); // 断开后停止心跳
|
||
}
|
||
}
|
||
|
||
void MyTcpClient::onErrorOccurred(QAbstractSocket::SocketError socketError) {
|
||
Q_UNUSED(socketError)
|
||
qDebug() << "Socket error:" << socket->errorString();
|
||
emit errorOccurred(socket->errorString());
|
||
}
|
||
|
||
void MyTcpClient::onReconnect() {
|
||
if (socket->state() == QAbstractSocket::UnconnectedState) {
|
||
qDebug() << "Reconnecting to" << serverHost << ":" << serverPort;
|
||
socket->connectToHost(serverHost, serverPort);
|
||
}
|
||
}
|