当前位置: 首页 > news >正文

QT之QLocalSocket下的两进程互相守护

在Qt应用程序开发中,进程间通信(IPC)是一个常见的需求。QLocalSocket是Qt提供的一个强大的本地套接字类,它通过基于套接字的接口,使多个进程能够无缝交换数据,非常适合需要本地通信的场景。专门用于同一台机器上不同进程之间的高效通信。与传统的TCP/UDP网络套接字不同,QLocalSocket使用本地套接字(在Unix系统上通常是Unix域套接字,在Windows上是命名管道),提供了更高的性能和更低的延迟。

一、QLocalSocket的特点

优势

  • 高性能: 本地通信避免了网络协议栈的开销
  • 安全性: 通信仅限于本机,不会暴露到网络
  • 简单易用: API设计与QTcpSocket类似,学习成本低
  • 跨平台: 在不同操作系统上提供一致的接口

适用场景

  • 主进程与子进程之间的数据交换
  • 多个独立应用程序之间的协作
  • 客户端-服务器架构的本地应用
  • 进程间状态同步和事件通知

基本概念

QLocalSocket通常与QLocalServer配对使用:

  • QLocalServer: 作为服务器端,监听连接请求
  • QLocalSocket: 作为客户端,连接到服务器

二、两进程互相守护示例

1、简述 

因为这个守护逻辑可以抽象成一个独立类GuardianService,只需传入:

  • 本进程名称(或 socket 名)

  • 对方进程名称

  • 对方启动路径(用于崩溃后重启)

2、源码示例

// GuardianService.h
#ifndef GUARDIANSERVICE_H
#define GUARDIANSERVICE_H#include <QObject>
#include <QLocalServer>
#include <QLocalSocket>
#include <QTimer>
#include <QProcess>
#include <QDebug>class GuardianService : public QObject {Q_OBJECT
public:static GuardianService* init(const QString &selfSocketName,const QString &peerSocketName,const QString &peerExecutablePath,QObject *parent = nullptr);private:explicit GuardianService(const QString &selfName,const QString &peerName,const QString &peerPath,QObject *parent = nullptr);void start();void setupServer();void connectToPeer();void tryRestartPeer();private slots:void onNewConnection();void onHeartbeatReceived();void onHeartbeatTimeout();void onPeerDisconnected();private:QString selfSocket;QString peerSocket;QString peerPath;QLocalServer server;QLocalSocket *peerClientSocket;QTimer heartbeatSendTimer;QTimer heartbeatTimeoutTimer;
};#endif // GUARDIANSERVICE_H// GuardianService.cpp
#include "GuardianService.h"GuardianService* GuardianService::init(const QString &selfSocketName,const QString &peerSocketName,const QString &peerExecutablePath,QObject *parent) {GuardianService *service = new GuardianService(selfSocketName, peerSocketName, peerExecutablePath, parent);service->start();return service;
}GuardianService::GuardianService(const QString &selfName,const QString &peerName,const QString &peerPath,QObject *parent): QObject(parent),selfSocket(selfName),peerSocket(peerName),peerPath(peerPath),peerClientSocket(new QLocalSocket(this)) {connect(&heartbeatSendTimer, &QTimer::timeout, this, [this]() {if (peerClientSocket->state() == QLocalSocket::ConnectedState) {peerClientSocket->write("ping");peerClientSocket->flush();}});connect(&heartbeatTimeoutTimer, &QTimer::timeout, this, &GuardianService::onHeartbeatTimeout);connect(peerClientSocket, &QLocalSocket::disconnected, this, &GuardianService::onPeerDisconnected);
}void GuardianService::start() {setupServer();connectToPeer();heartbeatSendTimer.start(2000);     // 每2秒发送心跳heartbeatTimeoutTimer.start(5000);  // 最多5秒无回应
}void GuardianService::setupServer() {QLocalServer::removeServer(selfSocket);if (!server.listen(selfSocket)) {qWarning() << "[Guardian] Failed to listen on socket:" << selfSocket << server.errorString();return;}connect(&server, &QLocalServer::newConnection, this, &GuardianService::onNewConnection);
}void GuardianService::connectToPeer() {if (peerClientSocket->state() != QLocalSocket::UnconnectedState)peerClientSocket->abort();peerClientSocket->connectToServer(peerSocket);
}void GuardianService::onNewConnection() {QLocalSocket *incoming = server.nextPendingConnection();connect(incoming, &QLocalSocket::readyRead, this, &GuardianService::onHeartbeatReceived);connect(incoming, &QLocalSocket::disconnected, incoming, &QLocalSocket::deleteLater);
}void GuardianService::onHeartbeatReceived() {heartbeatTimeoutTimer.start(5000);  // 重置超时计时器QLocalSocket *sender = qobject_cast<QLocalSocket *>(sender());if (sender) sender->readAll();
}void GuardianService::onHeartbeatTimeout() {qWarning() << "[Guardian] Peer timeout, attempting restart...";tryRestartPeer();
}void GuardianService::onPeerDisconnected() {qWarning() << "[Guardian] Disconnected from peer. Reconnecting...";connectToPeer();
}void GuardianService::tryRestartPeer() {QProcess::startDetached(peerPath);heartbeatTimeoutTimer.start(5000); // 等待新实例心跳
}

3、使用方法

在进程 A 启动代码中调用:

GuardianService::init("procA", "procB", "procB.exe");

在进程 B 中使用:

GuardianService::init("procB", "procA", "procA.exe");

4、总结

  • 利用 QLocalSocket 无需占用 TCP/UDP 端口;

  • 采用非侵入式心跳通信机制;

  • 一方挂掉后 3 秒内自动拉起;

  • 不依赖任务管理器或进程列表扫描;

  • 轻量、跨平台。

http://www.dtcms.com/a/314754.html

相关文章:

  • Nexus配置npm私有仓库
  • 开源的现代数据探索和可视化平台:Apache Superset 使用 Docker Compose
  • 单片机裸机程序设计架构
  • MLIR Introduction
  • Linux84 SHELL编程:流程控制 前瞻(1)
  • 数字信号处理_编程实例1
  • 京东开源新框架DripTable:轻量高效的企业级动态列表解决方案
  • 贪心算法
  • 基于Matlab的人脸识别签到系统
  • 前后端流式交互的几种方式
  • 学习嵌入式第十九天
  • 向日葵参考基因组
  • Day49 Java面向对象04 类与对象的创建
  • 【赵渝强老师】达梦数据库的DMSQL
  • Dify的部署(Docker Desktop )
  • 【Python小工具】图片转PDF
  • 破除陈规陋习的有效措施
  • Dynamic Programming【DP】2
  • RAG中的评估指标总结:BLEU、ROUGE、 MRR、MAP、nDCG、Precision@k、Recall@k 等
  • AR远程协作网页设计:虚实融合场景下的故障标注与操作指引界面
  • cf--思维训练
  • Git如何为多平台配置密钥和用户信息?
  • Git简易教程
  • PEAFOWL-IEEE-2025
  • Integer Types Range and varieties
  • 20250723-算法分析与设计之旅行商问题(Traveling Salesman Problem,TSP)
  • Antlr学习笔记 01、maven配置Antlr4插件案例Demo
  • golang的数组
  • SpringBoot-手动配置环境
  • VUE2 学习笔记17 路由