QT写一个TCP服务器和客户端程序,若一次没连接上。等待一秒重新连接,最多连接5次,否则连接失败,连接成功后30心跳一次
时间: 2023-07-31 19:14:04 浏览: 81
QT下TCP通信服务器端和客户端程序
下面是一个简单的示例代码,实现了一个TCP服务器和客户端程序,包括自动重连和心跳:
TCP服务器:
```cpp
#include <QTcpServer>
#include <QTcpSocket>
#include <QTimer>
class TcpServer : public QTcpServer
{
Q_OBJECT
public:
explicit TcpServer(QObject *parent = nullptr);
protected:
void incomingConnection(qintptr handle) override;
signals:
void dataReceived(QByteArray data);
private slots:
void onReadyRead();
void onDisconnected();
void onHeartbeat();
private:
QTcpSocket *m_socket;
QByteArray m_buffer;
QTimer m_heartbeatTimer;
int m_heartbeatCount;
};
TcpServer::TcpServer(QObject *parent)
: QTcpServer(parent)
, m_socket(nullptr)
, m_heartbeatCount(0)
{
connect(&m_heartbeatTimer, &QTimer::timeout, this, &TcpServer::onHeartbeat);
m_heartbeatTimer.start(30000); // 30秒一次心跳
}
void TcpServer::incomingConnection(qintptr handle)
{
if (!m_socket)
{
m_socket = new QTcpSocket(this);
connect(m_socket, &QTcpSocket::readyRead, this, &TcpServer::onReadyRead);
connect(m_socket, &QTcpSocket::disconnected, this, &TcpServer::onDisconnected);
m_socket->setSocketDescriptor(handle);
}
}
void TcpServer::onReadyRead()
{
m_buffer.append(m_socket->readAll());
while (m_buffer.size() >= 4)
{
int length = qFromLittleEndian<int>(m_buffer.left(4));
if (m_buffer.size() < length + 4)
break;
emit dataReceived(m_buffer.mid(4, length));
m_buffer = m_buffer.mid(length + 4);
}
}
void TcpServer::onDisconnected()
{
if (m_socket)
{
m_socket->deleteLater();
m_socket = nullptr;
m_heartbeatCount = 0;
}
}
void TcpServer::onHeartbeat()
{
if (m_socket)
{
QByteArray data;
QDataStream stream(&data, QIODevice::WriteOnly);
stream.setByteOrder(QDataStream::LittleEndian);
stream << qint32(0);
stream << qint8(0);
stream << qint8(0);
stream << qint8(0);
stream.device()->seek(0);
stream << qint32(data.size() - 4);
m_socket->write(data);
m_socket->flush();
++m_heartbeatCount;
if (m_heartbeatCount >= 5)
{
m_socket->disconnectFromHost();
m_heartbeatCount = 0;
}
}
}
```
TCP客户端:
```cpp
#include <QTcpSocket>
#include <QTimer>
class TcpClient : public QObject
{
Q_OBJECT
public:
explicit TcpClient(QObject *parent = nullptr);
void connectToHost(const QString &host, quint16 port);
signals:
void connected();
void disconnected();
void dataReceived(QByteArray data);
private slots:
void onConnected();
void onReadyRead();
void onDisconnected();
void onReconnect();
private:
QTcpSocket *m_socket;
QByteArray m_buffer;
QTimer m_reconnectTimer;
int m_reconnectCount;
QTimer m_heartbeatTimer;
int m_heartbeatCount;
};
TcpClient::TcpClient(QObject *parent)
: QObject(parent)
, m_socket(nullptr)
, m_reconnectCount(0)
, m_heartbeatCount(0)
{
connect(&m_reconnectTimer, &QTimer::timeout, this, &TcpClient::onReconnect);
connect(&m_heartbeatTimer, &QTimer::timeout, this, [this]()
{
if (m_socket)
{
QByteArray data;
QDataStream stream(&data, QIODevice::WriteOnly);
stream.setByteOrder(QDataStream::LittleEndian);
stream << qint32(0);
stream << qint8(0);
stream << qint8(0);
stream << qint8(0);
stream.device()->seek(0);
stream << qint32(data.size() - 4);
m_socket->write(data);
m_socket->flush();
++m_heartbeatCount;
if (m_heartbeatCount >= 5)
{
m_socket->disconnectFromHost();
m_heartbeatCount = 0;
}
}
});
m_reconnectTimer.start(1000); // 1秒后自动重连
m_heartbeatTimer.start(30000); // 30秒一次心跳
}
void TcpClient::connectToHost(const QString &host, quint16 port)
{
if (!m_socket)
{
m_socket = new QTcpSocket(this);
connect(m_socket, &QTcpSocket::connected, this, &TcpClient::onConnected);
connect(m_socket, &QTcpSocket::readyRead, this, &TcpClient::onReadyRead);
connect(m_socket, &QTcpSocket::disconnected, this, &TcpClient::onDisconnected);
m_socket->connectToHost(host, port);
}
}
void TcpClient::onConnected()
{
m_reconnectCount = 0;
m_heartbeatCount = 0;
m_reconnectTimer.stop();
emit connected();
}
void TcpClient::onReadyRead()
{
m_buffer.append(m_socket->readAll());
while (m_buffer.size() >= 4)
{
int length = qFromLittleEndian<int>(m_buffer.left(4));
if (m_buffer.size() < length + 4)
break;
emit dataReceived(m_buffer.mid(4, length));
m_buffer = m_buffer.mid(length + 4);
}
}
void TcpClient::onDisconnected()
{
if (m_socket)
{
m_socket->deleteLater();
m_socket = nullptr;
m_heartbeatCount = 0;
m_reconnectTimer.start(1000); // 1秒后自动重连
}
}
void TcpClient::onReconnect()
{
if (!m_socket && m_reconnectCount < 5)
{
m_socket = new QTcpSocket(this);
connect(m_socket, &QTcpSocket::connected, this, &TcpClient::onConnected);
connect(m_socket, &QTcpSocket::readyRead, this, &TcpClient::onReadyRead);
connect(m_socket, &QTcpSocket::disconnected, this, &TcpClient::onDisconnected);
m_socket->connectToHost("127.0.0.1", 1234);
++m_reconnectCount;
}
else if (m_socket)
{
m_reconnectTimer.stop();
}
}
```
使用示例:
```cpp
TcpServer server;
QObject::connect(&server, &TcpServer::dataReceived, [](QByteArray data)
{
qDebug() << "Server received data:" << data;
});
TcpClient client;
QObject::connect(&client, &TcpClient::connected, [&client]()
{
qDebug() << "Client connected";
client.connectToHost("127.0.0.1", 1234);
});
QObject::connect(&client, &TcpClient::disconnected, []()
{
qDebug() << "Client disconnected";
});
QObject::connect(&client, &TcpClient::dataReceived, [](QByteArray data)
{
qDebug() << "Client received data:" << data;
});
server.listen(QHostAddress::Any, 1234);
client.connectToHost("127.0.0.1", 1234);
```
注意:在实际应用中,应该根据具体的需求调整心跳间隔和重连次数等参数。
阅读全文