QT进程间通信(IPC)QLocalServer、QLocalSocket

QT实现进程守护的代码与运行说明

 1,本文目的

近期做嵌入式linux网关通信采集项目时,有如下需求:

-> 要采集不同类型的设备,可能会遇到N种协议,考虑每种协议单独进程管理

-> 单独的联网上报进程

-> 单独的远程升级进程

此时出现了一个问题,如果在设备运行过程中,其中一个或多个进程异常关闭,可能会导致设备工作异常。解决思路参网上照进程守护进行监听进程并对异常关闭进程做重启工作,思路如下:

启动守护进程 -> 按照配置列表启动子进程 -> 定时查询进程PID -> 重启异常关闭子进程

但是之前工作中遇到过,进程异常不工作但是PID依然还在的情况于是想到了进程间通信,类似于心跳。

通过查询网上的案例,各有优缺点,有的作为父进程启动子进程进行管理与通信,有的需要扫描共享内存……不再讨论以上这些方法,本文只讨论QLocalServer、QLocalSocket实现方式参照QT例程的“Fortune”如下图,进行记录实现方法。

 2,代码实现

代码分两部分,服务器端和客户端。我的思路是,每个协议进程作为服务器端进行监听,进程守护作为客户端定时连接接受数据。

服务器端代码:

prog1.pro

QT -= gui
QT += network
CONFIG += c++11 console
CONFIG -= app_bundle

DESTDIR = /home/went/test/bin

# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
        main.cpp \
        server.cpp

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

HEADERS += \
    server.h

main.cpp

#include <QCoreApplication>
#include <QDebug>
#include "server.h"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    server w;
    return a.exec();
}

server.h

#ifndef SERVER_H
#define SERVER_H

#include <QObject>
#include <QString>
#include <QDebug>
#include <QLocalServer>
#include <QLocalSocket>

class server : public QObject
{
    Q_OBJECT
public:
    explicit server(QObject *parent = nullptr);
    ~server();

private slots:
    void sendData();

private:
    QLocalServer *prog1Server;
    QStringList fortunes;

};

#endif // SERVER_H

server.cpp

#include "server.h"
//#include <stdlib.h>
//#include <qlocalserver.h>
//#include <qlocalsocket.h>

server::server(QObject *parent) : QObject(parent)
{
    prog1Server = new QLocalServer;
    prog1Server->removeServer("prog1");
    if (!prog1Server->listen("prog1")) {
        qDebug() << QString("Unable to start the server: %1.").arg(prog1Server->errorString()) << endl;

        return;
    }

    connect(prog1Server, &QLocalServer::newConnection, this, &server::sendData);
    qDebug() << "prog1 is openned !" << endl;
}
server::~server() {
    if(prog1Server != nullptr) {
        prog1Server->close();
        delete prog1Server;
    }
}
void server::sendData() {
    QLocalSocket *clientConnection = prog1Server->nextPendingConnection();
    connect(clientConnection, &QLocalSocket::disconnected,
            clientConnection, &QLocalSocket::deleteLater);

    clientConnection->write("ok");
    qDebug() << "reply ok !" << endl;
    clientConnection->waitForBytesWritten();
    clientConnection->disconnectFromServer();
}

客户端代码:

deamon.pro

QT -= gui
QT += network

CONFIG += c++11 console
CONFIG -= app_bundle
DESTDIR = /home/went/test/bin
# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
        client.cpp \
        main.cpp

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

HEADERS += \
    client.h

main.cpp

#include <QCoreApplication>
#include <QDebug>
#include <QProcess>
#include <client.h>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    client w;
    return a.exec();
}

client.h

#ifndef CLIENT_H
#define CLIENT_H

#include <QObject>
#include <QLocalSocket>
#include <QThread>
class client : public QObject
{
    Q_OBJECT
public:
    explicit client(QObject *parent = nullptr);

private slots:
    void requestNewFortune();
    void readFortune();
    void displayError(QLocalSocket::LocalSocketError socketError);

private:
QLocalSocket *socket;

};

#endif // CLIENT_H

client.cpp

#include "client.h"

client::client(QObject *parent) : QObject(parent),
    socket(new QLocalSocket(this))
{

    system("./prog1 &");
    QThread::sleep(5);
    qDebug() << "start" << endl;
    connect(socket, &QLocalSocket::readyRead, this, &client::readFortune);
    connect(socket, QOverload<QLocalSocket::LocalSocketError>::of(&QLocalSocket::error),
            this, &client::displayError);
    requestNewFortune();
}
void client::requestNewFortune()
{
    socket->abort();
    socket->connectToServer("prog1");
}

void client::readFortune()
{


    QString data;
    data =  socket->readAll();
    qDebug() << "client received: " << data << endl;

}

void client::displayError(QLocalSocket::LocalSocketError socketError)
{
    if (socketError != QLocalSocket::PeerClosedError) {
        qDebug() << "something error: " << socketError << endl;
    }
}

3,运行说明

客户端程序在构建函数里加入了启动服务器端指令(限Linux),将编译后的可执行程序放在同一个文件夹下,只需要执行客户端程序即可完成测试。测试结果如下图:

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值