Qt5 C++ TcpSocket 如何判断是服务主动断开tcp socket连接?

news2025/2/22 7:00:31

文章目录

      • 实现思路
      • 示例代码
      • 代码解释
      • 主要功能和用法
      • 注意事项

在 Qt 5.9.9 的 C++ 开发中,使用 QTcpSocket 时,要判断是服务端主动断开 TCP Socket 连接,可以通过处理 QTcpSocketdisconnected 信号,结合 QTcpSocket 的状态以及相关事件信息来综合判断。以下是具体的实现思路和示例代码:

实现思路

  1. 监听 disconnected 信号:当连接断开时,QTcpSocket 会发出 disconnected 信号,我们可以在槽函数中处理该信号。
  2. 检查连接状态:在 disconnected 信号的槽函数中,检查 QTcpSocket 的状态,判断是否为主动断开。可以结合网络错误码、服务端发送的特定消息等进行判断。
  3. 服务端主动断开的特征判断:例如,如果服务端在断开连接前发送了特定的关闭消息,客户端接收到该消息后就可以知道是服务端主动断开;或者通过网络错误码判断是否是服务端正常关闭连接。
    在这里插入图片描述

示例代码

#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();
}

代码解释

  1. MyTcpClient:继承自 QObject,封装了 QTcpSocket 对象,用于处理与服务端的连接。
  2. 构造函数:创建 QTcpSocket 对象,并连接 disconnectedreadyRead 信号到相应的槽函数。然后尝试连接到服务端。
  3. onDisconnected 槽函数:在连接断开时被调用,检查 QTcpSocket 的状态和错误码。如果错误码为 QAbstractSocket::RemoteHostClosedError,则表示服务端主动断开连接。
  4. 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();

注意事项

  • 上述示例中的错误码判断和特定消息判断只是一种常见的方式,具体的判断逻辑需要根据实际的业务需求和服务端的实现进行调整。
  • 确保服务端和客户端对断开连接的消息和状态处理达成一致,避免出现误解。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2303273.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

DeepSeek动画视频全攻略:从架构到本地部署

DeepSeek 本身并不直接生成动画视频,而是通过与一系列先进的 AI 工具和传统软件协作,完成动画视频的制作任务。这一独特的架构模式,使得 DeepSeek 在动画视频创作领域发挥着不可或缺的辅助作用。其核心流程主要包括脚本生成、画面设计、视频合成与后期处理这几个关键环节。 …

电力通信物联网应用,国密网关守护电力数据安全

电力国密网关是用于保护电力调度数据网路由器和电力系统的局域网之间通信安全的电力专用网关机&#xff0c;主要为上下级控制系统之间的广域网通信提供认证与加密服务&#xff0c;实现数据传输的机密性、完整性。 国密算法网关功能特点 身份认证&#xff1a;对接入的设备和用户…

Datawhale Ollama教程笔记5

Dify 接入 Ollama 部署的本地模型 Dify 支持接入 Ollama 部署的大型语言模型推理和 embedding 能力。 快速接入 下载 Ollama 访问 Ollama 安装与配置&#xff0c;查看 Ollama 本地部署教程。 运行 Ollama 并与 Llama 聊天 ollama run llama3.1Copy to clipboardErrorCopied …

保姆级! 本地部署DeepSeek-R1大模型 安装Ollama Api 后,Postman本地调用 deepseek

要在Postman中访问Ollama API并调用DeepSeek模型&#xff0c;你需要遵循以下步骤。首先&#xff0c;确保你有一个有效的Ollama服务器实例运行中&#xff0c;并且DeepSeek模型已经被加载。 可以参考我的这篇博客 保姆级&#xff01;使用Ollama本地部署DeepSeek-R1大模型 并java…

ASP.NET Core 下载文件

本文使用 ASP .NET Core&#xff0c;适用于 .NET Core 3.1、.NET 5、.NET 6和.NET 8。 另请参阅&#xff1a; 如何在将文件发送到浏览器后自动删除该文件。 如何将文件从浏览器上传到服务器。 如何在 ASP.NET Core 应用程序中从 URL/URI 下载文件。 如果使用.NET Framework&am…

【信息系统项目管理师-案例真题】2022下半年案例分析答案和详解

更多内容请见: 备考信息系统项目管理师-专栏介绍和目录 文章目录 试题一(24分)【问题1】(6分)【问题2】(10分)【问题3】(8分)试题二(26分)【问题1】(8分)【问题2】(8分)【问题3】(4分)【问题4】(6分)试题三(25分)【问题1】(12分)【问题2】(7分)【问题…

原来DeepSeek还能运用在系统集成-领星对接

在当今数字化转型的浪潮中&#xff0c;企业的信息化建设已成为提升运营效率、优化管理流程的关键。领星ERP与金蝶云星空作为两款在电商和财务管理领域广受欢迎的软件&#xff0c;其数据对接对于跨境电商企业来说尤为重要。本文将结合实际应用场景&#xff0c;深度解析如何通过轻…

在windows下安装windows+Ubuntu16.04双系统(上)

这篇文章的内容主要来源于这篇文章&#xff0c;给文章很详细的介绍了如何从windows下安装windowsubuntu16.04双系统。我刚开始装双系统都是参照这个方法&#xff0c;该作者前后更新了两个版本&#xff0c;在这里对其稍微进行整理一下。 一、准备&#xff1a;&#xff08;这里推…

第37章 合作之路与占坑成功

在春寒料峭的时节&#xff0c;那丝丝寒意宛如一缕缕若有若无的轻烟&#xff0c;在空气中悄然弥漫。锐创所的会议室&#xff0c;宛如一个被岁月尘封的神秘空间&#xff0c;暖黄色的灯光晕染开来&#xff0c;像是为整个房间披上了一层朦胧的薄纱&#xff0c;陈旧却又带着几分温馨…

杰和科技GAM-AI视觉识别管理系统,让AI走进零售营销

在数字化浪潮席卷全球零售业的今天&#xff0c;如何精准触达顾客需求、优化运营效率、提升门店业绩&#xff0c;成为实体商业破局的关键。 GAM-AI视觉识别管理系统 杰和科技智能零售管理系统&#xff1a;GAM-AI视觉识别管理系统&#xff0c;以AI视觉识别大数据分析边缘计算为核…

golang内存泄漏

golang也用了好几年了&#xff0c;趁着有空 整理归纳下&#xff0c;以后忘了好看下 一般认为 Go 10次内存泄漏&#xff0c;8次goroutine泄漏&#xff0c;1次是真正内存泄漏&#xff0c;还有1次是cgo导致的内存泄漏 1:环境 go1.20 win10 2:goroutine泄漏 单个Goroutine占用内存&…

Redis存储⑩Redis的事务_弱化的原子性

目录 1. MySQL和Redis事务的区别 1.1 MySQL的事务 1.2 Redis的事务 2. Redis事务操作 2.1 MULTI multi 2.2 EXEC exec 2.3 DISCARD discard 2.4 WATCH 1. MySQL和Redis事务的区别 1.1 MySQL的事务 MySQL事务复习&#xff1a; MySQL数据库⑨_事务&#xff08;四个属性…

基于Flask的京东商品信息可视化分析系统的设计与实现

【Flask】基于Flask的京东商品信息可视化分析系统的设计与实现&#xff08;完整系统源码开发笔记详细部署教程&#xff09;✅ 目录 一、项目简介二、项目界面展示三、项目视频展示 一、项目简介 系统能够灵活地执行SQL查询&#xff0c;提取出用于分析的关键数据指标。为了将这…

QML ToolButton与DelayButton的使用、详解与自定义样式

QML MenuBarItem与MenuItem的使用、详解与自定义样式 一、介绍1、ToolButton常见用法基础示例设置图标 常用属性texticonenabledshortcutcheckable & checked 信号onClickedonPressed 和 onReleased 样式和外观使用场景 2、DelayButton使用场景核心属性1. delay 核心信号1.…

JSON格式,C语言自己实现,以及直接调用库函数(一)

JSON&#xff08;JavaScript Object Notation&#xff09;是一种轻量级的数据交换格式&#xff0c;易于人阅读和编写&#xff0c;同时也易于机器解析和生成。以下为你提供不同场景下常见的 JSON 格式示例。 1. 简单对象 JSON 对象是由键值对组成&#xff0c;用花括号 {} 包裹&…

学习整理安装php的uuid扩展以及uuid调用方法

学习整理安装php的uuid扩展以及uuid调用方法 1、安装uuid依赖库2、下载并安装3、ini中添加扩展4、re2c版本报错5、uuid调用方法 1、安装uuid依赖库 yum -y install uuid uuid-devel e2fsprogs-devel libuuid-devel2、下载并安装 点我下载uuid安装包 wget http://pecl.php.ne…

Orange 单体架构 - 快速启动

1 后端服务 1.1 基础设施 组件说明版本MySQLMySQL数据库服务5.7/8JavaJava17redis-stackRedis向量数据库最新版本Node安装Node22.11.0 1.2 orange-dependencies-parent 项目Maven依赖版本管理 1.2.1 项目克隆 GitHub git clone https://github.com/hengzq/orange-depende…

Spring Boot 入门 与 无法解析符号 springframework 的解决

Spring Boot 入门的关键步骤 1 创建 Maven 工程 操作目的&#xff1a; 通过 Maven 工程来管理项目依赖&#xff0c;Spring Boot 本身就依赖 Maven 或 Gradle 来简化依赖管理。 操作方法&#xff1a; 打开 IDEA&#xff08;IntelliJ IDEA&#xff09;。点击 New Project&#…

3D模型在线转换工具:轻松实现3DM转OBJ

3D模型在线转换是一款功能强大的在线工具&#xff0c;支持多种3D模型格式的在线预览和互转。无论是工业设计、建筑设计&#xff0c;还是数字艺术领域&#xff0c;这款工具都能满足您的需求。 3DM与OBJ格式简介 3DM格式&#xff1a;3DM是一种广泛应用于三维建模的文件格式&…

网络安全-js安全知识点与XSS常用payloads

简介 JavaScript 是一种轻量级的编程语言&#xff0c;定义了HTML的行为。它与Java的关系类似周杰和周杰伦的关系&#xff08;即没有关系&#xff09;。 用法 HTML 中的脚本必须位于 <script> 与 </script> 标签之间。 脚本可被放置在 HTML 页面的 <body>…