在 Qt 5.9.9 的 C++ 开发中,使用
QTcpSocket
时,要判断是服务端主动断开 TCP Socket 连接,可以通过处理 QTcpSocket
的 disconnected
信号,结合 QTcpSocket
的状态以及相关事件信息来综合判断。以下是具体的实现思路和示例代码:
实现思路
- 监听
disconnected
信号:当连接断开时,QTcpSocket
会发出disconnected
信号,我们可以在槽函数中处理该信号。 - 检查连接状态:在
disconnected
信号的槽函数中,检查QTcpSocket
的状态,判断是否为主动断开。可以结合网络错误码、服务端发送的特定消息等进行判断。 - 服务端主动断开的特征判断:例如,如果服务端在断开连接前发送了特定的关闭消息,客户端接收到该消息后就可以知道是服务端主动断开;或者通过网络错误码判断是否是服务端正常关闭连接。
示例代码
#include <QtNetwork/QTcpSocket>
#include <QDebug>
#include <QCoreApplication>
class MyTcpClient : public QObject
{
Q_OBJECT
public:
MyTcpClient(QObject *parent = nullptr) : QObject(parent)
{
socket = new QTcpSocket(this);
connect(socket, &QTcpSocket::disconnected, this, &MyTcpClient::onDisconnected);
connect(socket, &QTcpSocket::readyRead, this, &MyTcpClient::onReadyRead);
// 连接到服务端
socket->connectToHost("127.0.0.1", 12345);
}
private slots:
void onDisconnected()
{
// 检查是否是服务端主动断开
if (socket->state() == QAbstractSocket::UnconnectedState) {
// 可以进一步根据错误码判断
if (socket->error() == QAbstractSocket::RemoteHostClosedError) {
qDebug() << "Server主动断开连接";
} else {
qDebug() << "连接断开,错误码:" << socket->errorString();
}
}
}
void onReadyRead()
{
QByteArray data = socket->readAll();
// 假设服务端发送 "CLOSE_CONNECTION" 表示主动断开连接
if (data == "CLOSE_CONNECTION") {
qDebug() << "收到服务端断开连接消息,即将断开连接";
socket->disconnectFromHost();
}
}
private:
QTcpSocket *socket;
};
#include "main.moc"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
MyTcpClient client;
return a.exec();
}
#include <QtNetwork/QTcpServer>
#include <QtNetwork/QTcpSocket>
#include <QDebug>
#include <QCoreApplication>
class MyServer : public QTcpServer
{
Q_OBJECT
public:
explicit MyServer(QObject *parent = nullptr) : QTcpServer(parent) {}
protected:
void incomingConnection(qintptr socketDescriptor) override
{
QTcpSocket *socket = new QTcpSocket(this);
if (!socket->setSocketDescriptor(socketDescriptor)) {
qDebug() << "Failed to set socket descriptor.";
delete socket;
return;
}
connect(socket, &QTcpSocket::readyRead, this, [socket]() {
QByteArray data = socket->readAll();
qDebug() << "Received from client:" << data;
// 将收到的数据原样返回给客户端
socket->write(data);
});
connect(socket, &QTcpSocket::disconnected, socket, &QTcpSocket::deleteLater);
}
};
#include "server.moc"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
MyServer server;
if (!server.listen(QHostAddress::Any, 12345)) {
qDebug() << "Server could not start!";
} else {
qDebug() << "Server started!";
}
return a.exec();
}
#include <QtNetwork/QTcpSocket>
#include <QDebug>
#include <QCoreApplication>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QTcpSocket socket;
socket.connectToHost(QHostAddress::LocalHost, 12345);
if (socket.waitForConnected()) {
qDebug() << "Connected to server!";
// 向服务器发送消息
socket.write("Hello, server!");
socket.waitForBytesWritten();
if (socket.waitForReadyRead()) {
QByteArray data = socket.readAll();
qDebug() << "Received from server:" << data;
}
} else {
qDebug() << "Connection failed!";
}
socket.disconnectFromHost();
if (socket.state() != QAbstractSocket::UnconnectedState) {
socket.waitForDisconnected();
}
return a.exec();
}
代码解释
MyTcpClient
类:继承自QObject
,封装了QTcpSocket
对象,用于处理与服务端的连接。- 构造函数:创建
QTcpSocket
对象,并连接disconnected
和readyRead
信号到相应的槽函数。然后尝试连接到服务端。 onDisconnected
槽函数:在连接断开时被调用,检查QTcpSocket
的状态和错误码。如果错误码为QAbstractSocket::RemoteHostClosedError
,则表示服务端主动断开连接。onReadyRead
槽函数:在有数据可读时被调用,检查服务端发送的数据。如果收到特定的关闭消息(如 “CLOSE_CONNECTION”),则认为服务端要主动断开连接,调用disconnectFromHost()
方法断开连接。
主要功能和用法
- 1 包含必要的头文件
在使用 QTcpSocket 之前,需要包含相应的头文件,并在 .pro 文件中添加 QT += network 以引入网络模块。
#include <QtNetwork/QTcpSocket>
- 2 创建 QTcpSocket 对象
QTcpSocket *socket = new QTcpSocket(this);
- 3 连接到服务器(客户端)
socket->connectToHost(QHostAddress::LocalHost, 12345);
// 可以使用 waitForConnected 等待连接成功
if (socket->waitForConnected()) {
qDebug() << "Connected to server!";
} else {
qDebug() << "Connection failed!";
}
- 4.发送数据
QByteArray data = "Hello, server!";
socket->write(data);
// 可以使用 waitForBytesWritten 等待数据发送完成
if (socket->waitForBytesWritten()) {
qDebug() << "Data sent successfully!";
}
- 5.接收数据
// 连接 readyRead 信号到槽函数
connect(socket, &QTcpSocket::readyRead, this, [socket]() {
QByteArray data = socket->readAll();
qDebug() << "Received data:" << data;
});
- 6.断开连接
socket->disconnectFromHost();
// 可以使用 waitForDisconnected 等待断开连接完成
if (socket->waitForDisconnected()) {
qDebug() << "Disconnected from server!";
}
- 7.错误处理
connect(socket, QOverload<QAbstractSocket::SocketError>::of(&QTcpSocket::error),
[](QAbstractSocket::SocketError socketError) {
qDebug() << "Socket error:" << socketError;
});
// 获取错误信息
qDebug() << "Error message:" << socket->errorString();
注意事项
- 上述示例中的错误码判断和特定消息判断只是一种常见的方式,具体的判断逻辑需要根据实际的业务需求和服务端的实现进行调整。
- 确保服务端和客户端对断开连接的消息和状态处理达成一致,避免出现误解。