TSI_Config/MyTcpClient.cpp
2025-05-07 19:46:31 +08:00

146 lines
4.8 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 "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秒重连一次
}
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() < sizeof(PackageHead)) {
return; // 数据不够,等待下次触发
}
// 读取头部
socket->read(reinterpret_cast<char*>(&m_currentHead), sizeof(PackageHead));
// 验证头部标识0xAA55AA
if (m_currentHead.head[0] != 0xAA ||
m_currentHead.head[1] != 0x55 ||
m_currentHead.head[2] != 0xAA) {
qWarning() << "Invalid header! Disconnecting...";
return;
}
// 进入等待数据状态
m_waitingForHeader = false;
m_buffer.clear();
m_buffer.append(reinterpret_cast<char*>(&m_currentHead), sizeof(PackageHead)); // 先存头部
} else {
// 2. 根据头部的 len 读取剩余数据
qint64 remainingBytes = m_currentHead.len - (m_buffer.size() - sizeof(PackageHead));
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() - sizeof(PackageHead) >= m_currentHead.len) {
qDebug() << "m_buffer" << m_buffer.size() << "bytes";
emit dataReceived(m_buffer);
m_waitingForHeader = true; // 准备接收下一个包
}
}
}
// QByteArray data = socket->readAll();
// emit dataReceived(data);
}
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);
}
}