QT项目_RPC(进程间通讯)

news2024/11/15 12:42:29

QT项目_RPC(进程间通讯)

前言:
两个进程间通信、或是说两个应用程序之间通讯。实际情况是在QT开发的一个项目中,里面包含两个子程序,子程序有单独的界面和应用逻辑,这两个子程序跑起来之后需要一些数据的交互,例如:一个程序是用户界面和用户程序,另一个程序时OSD菜单
注意:RPC通讯传输的数据类型有bool、int和std::string(QString不行)
效果演示:
在这里插入图片描述

1、移植RCP源码到自己工程

①移植RPC,说白了就是两个文件夹里面有N多个源文件,直接复制过来直接用,需要自行修改.pro文件以便加入编译
在这里插入图片描述
在这里插入图片描述

# rest_rpc
INCLUDEPATH += $$PWD/msgpack
DEPENDPATH += $$PWD/msgpack

②工程目录
在这里插入图片描述
在这里插入图片描述

2、源码展示
test_rpc.pro

TEMPLATE = subdirs

SUBDIRS += \
    apply \
    layer

apply/apply.pro

QT += quick \
    widgets

CONFIG += c++11

# 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). Refer to the documentation for the
# deprecated API 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 \
        mainwidget.cpp \
        rpc/MessageTip.cpp \
        rpc/RPCClient.cpp \
        rpc/RPCServer.cpp

RESOURCES += qml.qrc

# Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH =

# Additional import path used to resolve QML modules just for Qt Quick Designer
QML_DESIGNER_IMPORT_PATH =

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

# rest_rpc
INCLUDEPATH += $$PWD/msgpack
DEPENDPATH += $$PWD/msgpack

HEADERS += \
    mainwidget.h \
    rpc/MessageTip.h \
    rpc/RPCClient.h \
    rpc/RPCServer.h

apply/Headers/rpc/MessageTip.h

#ifndef MESSAGETIP_H
#define MESSAGETIP_H

#include <qstring.h>

namespace MessageTip
{
    void onApplyvalueChanged(int value);
    void onApplystringChanged(std::string value);
}

#endif // MESSAGETIP_H

apply/Headers/rpc/RPCClient.h

#ifndef RPCCLIENT_H
#define RPCCLIENT_H

#include "rest_rpc/rpc_client.hpp"

class RPCClient
{
public:
    RPCClient();

    static RPCClient *get_instance()
    {
        static RPCClient manage;
        return &manage;
    }

    /**
     * @brief 尝试连接RPC Server
     * @return true 连接成功,false 连接失败
     */
    void tryConnect();

    rest_rpc::rpc_client *getSocketObject();

private:
    rest_rpc::rpc_client *m_pClient = nullptr;
};

#endif // RPCCLIENT_H

apply/Headers/rpc/RPCServer.h

#ifndef RPCSERVER_H
#define RPCSERVER_H

#include <qstring.h>
#include "rest_rpc/rpc_server.h"

using namespace rest_rpc;
using namespace rpc_service;

class RPCServer
{
public:
    RPCServer();
    void setApplyvalue(rpc_conn conn , int value);
    void setApplystring(rpc_conn conn , std::string value);
};

#endif // RPCSERVER_H

apply/Headers/mainwidget.h

#ifndef MAINWIDGET_H
#define MAINWIDGET_H

#include <QObject>
#include <QWidget>
#include <QQmlComponent>
#include <QQmlApplicationEngine>
#include <QQuickItem>
#include "rpc/RPCServer.h"

class MainWidget : public QObject
{
    Q_OBJECT
public:
    MainWidget();

protected slots:
    void onClickPageNo(bool enable);
    void onApplyvalueChanged(int value);
    void onApplystringChanged(QString value);

private:
    QQuickItem *m_applyItem = nullptr;
    QObject *m_applyObject = nullptr;
    RPCServer *m_pRPCServer = nullptr;
};

#endif // MAINWIDGET_H

apply/Sources/rpc/MessageTip.cpp

#include "MessageTip.h"
#include "RPCClient.h"
#include "qdebug.h"


void MessageTip::onApplyvalueChanged(int value)
{
    try {
        RPCClient::get_instance()->getSocketObject()->call<void>("MessageTip::layervalueChanged", value);
    } catch (const std::exception &e) {
        qDebug() << "Exception {}", e.what();
    }
}

void MessageTip::onApplystringChanged(std::string value)
{
    try {
        RPCClient::get_instance()->getSocketObject()->call<void>("MessageTip::layerstringChanged", value);
    } catch (const std::exception &e) {
        qDebug() << "Exception {}", e.what();
    }
}

apply/Sources/rpc/RPCClient.cpp

#include "RPCClient.h"
#include <QtDebug>

RPCClient::RPCClient()
{

}

void RPCClient::tryConnect()
{
    m_pClient = new rest_rpc::rpc_client("127.0.0.1", 9000);
    m_pClient->enable_auto_reconnect(true);

    m_pClient->connect();

    std::thread([&] {
        while (true)
        {
            if (m_pClient->has_connected()) {
                qDebug() << "apply RPC connect success";

                break;
            } else {
                qDebug() << "apply RPC connect fail";
                std::this_thread::sleep_for(std::chrono::milliseconds(500));
            }
        }
    }).detach();
}

rest_rpc::rpc_client *RPCClient::getSocketObject()
{
    return m_pClient;
}

apply/Sources/rpc/RPCServer.cpp

#include "RPCServer.h"
#include "qdebug.h"

RPCServer::RPCServer()
{
    std::thread([&] {
        rpc_server server(9001, std::thread::hardware_concurrency());

        server.register_handler("MessageTip::setApplyvalue", &RPCServer::setApplyvalue, this);
        server.register_handler("MessageTip::setApplystring", &RPCServer::setApplystring, this);

        server.run();
    }).detach();
}

void RPCServer::setApplyvalue(rpc_conn conn , int value)
{
    //todo
    qDebug() << "apply recv :" << value;
}

void RPCServer::setApplystring(rpc_conn conn , std::string value)
{
    //todo
    qDebug() << "apply recv :" << QString::fromStdString(value);
}

apply/Sources/main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include "mainwidget.h"
#include "qdebug.h"
#include "qthread.h"

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

    QGuiApplication app(argc, argv);

//    QQmlApplicationEngine engine;
//    const QUrl url(QStringLiteral("qrc:/main.qml"));
//    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
//    &app, [url](QObject * obj, const QUrl & objUrl) {
//        if (!obj && url == objUrl) {
//            QCoreApplication::exit(-1);
//        }
//    }, Qt::QueuedConnection);
//    engine.load(url);

    MainWidget mainwidget;
    return app.exec();
}

apply/Sources/mainwidget.cpp

#include "mainwidget.h"
#include "qdebug.h"
#include "rpc/RPCClient.h"
#include "rpc/MessageTip.h"
#include <QProcess>

MainWidget::MainWidget()
{
    QQmlApplicationEngine *m_pEngine = new QQmlApplicationEngine;
    QQmlComponent component(m_pEngine, QUrl(QStringLiteral("qrc:/main.qml")));
    QObject *mainObject = component.create();
    if (mainObject == nullptr) {
        qDebug() << "mainObject fail";
        return;
    }

    QList<QObject *> objectList = mainObject->findChildren<QObject *>("mybutton");
    if (objectList.isEmpty()) {
        qDebug() << "mybutton failed\n";
        return;
    }
    m_applyObject = objectList.last();

    connect(m_applyObject, SIGNAL(applyvalueChanged(int)), this, SLOT(onApplyvalueChanged(int)));
    connect(m_applyObject, SIGNAL(applystringChanged(QString)), this, SLOT(onApplystringChanged(QString)));
    connect(mainObject, SIGNAL(window_interface(bool)), this, SLOT(onClickPageNo(bool)));

    m_pRPCServer = new RPCServer();
    RPCClient::get_instance()->tryConnect();
}

void MainWidget::onClickPageNo(bool enable)
{
    QProcess *process = new QProcess();
    process->start("/home/zhou/work/test/build-test_rpc-Desktop_Qt_5_14_2_GCC_64bit-Debug/layer/layer");
}

void MainWidget::onApplyvalueChanged(int value)
{
    qDebug() << "onApplyvalueChanged" << value;
    MessageTip::onApplyvalueChanged(value);
}

void MainWidget::onApplystringChanged(QString value)
{
    qDebug() << "onApplystringChanged" << value;
    MessageTip::onApplystringChanged(std::string(value.toLocal8Bit()));
}

apply/main.qml

import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12

Window {
    visible: true
    width: 640
    height: 480
    objectName: "apply_window"
    title: qsTr("Hello apply")

    signal window_interface(bool enable)

    Column{
        anchors.fill: parent
        spacing: 20
        Button{
            width: 140
            height: 50

            text: "开启界面2"
            onClicked: {
                window_interface(true)
            }
        }
        Mybutton{
            width: 140
            height: 300
        }
    }
}

apply/Mybutton.qml

import QtQuick 2.0
import QtQuick.Controls 2.12

Item {
    objectName: "mybutton"

    signal applyvalueChanged(int value)
    signal applystringChanged(string value)

    Column{
        spacing: 10
        Button{
            objectName: "button"
            width: 140
            height: 50

            text: "send1"

            onClicked: {
                applyvalueChanged(1)
            }
        }
        Button{
            width: 140
            height: 50

            text: "send2"

            onClicked: {
                applyvalueChanged(2)
            }
        }
        Button{
            width: 140
            height: 50

            text: "验证string"
            onClicked: {
                applystringChanged("{\"name\":\"lili\",\"age\":24,\"class\":6}")
            }
        }
    }
}

layer.pro

QT += quick
QT += widgets

CONFIG += c++11

# 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). Refer to the documentation for the
# deprecated API 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 \
        mainwidget.cpp \
        rpc/MessageTip.cpp \
        rpc/RPCClient.cpp \
        rpc/RPCServer.cpp

RESOURCES += qml.qrc

# Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH =

# Additional import path used to resolve QML modules just for Qt Quick Designer
QML_DESIGNER_IMPORT_PATH =

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

# rest_rpc
INCLUDEPATH += $$PWD/msgpack
DEPENDPATH += $$PWD/msgpack

HEADERS += \
    mainwidget.h \
    rpc/MessageTip.h \
    rpc/RPCClient.h \
    rpc/RPCServer.h

layer/Headers/rpc/MessageTip.h

#ifndef MESSAGETIP_H
#define MESSAGETIP_H

#include <qstring.h>

namespace MessageTip
{
    void setApplyvalue(int value);
    void setApplystring(std::string value);
}

#endif // MESSAGETIP_H

layer/Headers/rpc/RPCClient.h

#ifndef RPCCLIENT_H
#define RPCCLIENT_H

#include "rest_rpc/rpc_client.hpp"

class RPCClient
{
public:
    RPCClient();
    static RPCClient *get_instance()
    {
        static RPCClient layer_manage;
        return &layer_manage;
    }

    /**
     * @brief 尝试连接RPC Server
     * @return true 连接成功,false 连接失败
     */
    void tryConnect();

    rest_rpc::rpc_client *getSocketObject();

private:
    rest_rpc::rpc_client *m_pClient = nullptr;
};

#endif // RPCCLIENT_H

layer/Headers/rpc/RPCServer.h

#ifndef RPCSERVER_H
#define RPCSERVER_H

#include <QtDebug>
#include <QThread>
#include <QObject>
#include <QQuickItem>

#include "rest_rpc/rpc_server.h"
using namespace rest_rpc;
using namespace rpc_service;


class RPCServer : public QObject
{
    Q_OBJECT
public:
    explicit RPCServer(QObject *parent = nullptr);
    void layervalueChanged(rpc_conn conn , int value);
    void layerstringChanged(rpc_conn conn , std::string value);

protected:

signals:

private:
    QObject *m_pMainObject = nullptr;
    QQuickItem *m_pOSDAreaItem = nullptr;
};

#endif // RPCSERVER_H

layer/Headers/mainwidget.h

#ifndef MAINWIDGET_H
#define MAINWIDGET_H

#include <QObject>
#include <QQmlComponent>
#include <QQmlApplicationEngine>
#include <QQuickItem>
#include "rpc/RPCServer.h"

class mainwidget : public QObject
{
    Q_OBJECT
public:
    mainwidget();

private:
    RPCServer *m_pRPCServer = nullptr;
};

#endif // MAINWIDGET_H

layer/Sources/rpc/MessageTip.cpp

#include "MessageTip.h"
#include "RPCClient.h"
#include <QtDebug>


void MessageTip::setApplyvalue(int value)
{
    try {
        return RPCClient::get_instance()->getSocketObject()->call<void>("MessageTip::setApplyvalue", value);
    } catch (const std::exception &e) {
        qDebug() << "setImageRotate exception" << e.what();
    }
}

void MessageTip::setApplystring(std::string value)
{
    try {
        return RPCClient::get_instance()->getSocketObject()->call<void>("MessageTip::setApplystring", value);
    } catch (const std::exception &e) {
        qDebug() << "setImageRotate exception" << e.what();
    }
}

layer/Sources/rpc/RPCClient.cpp

#include "RPCClient.h"
#include <QtDebug>

RPCClient::RPCClient()
{

}

void RPCClient::tryConnect()
{
//#if defined(__x86_64)
//    m_pClient = new rest_rpc::rpc_client("192.168.31.95", 9001);
//#else
    m_pClient = new rest_rpc::rpc_client("127.0.0.1", 9001);
//#endif
    m_pClient->enable_auto_heartbeat(true);

    m_pClient->connect();
    std::thread([&] {
        while (true)
        {
            qDebug() << "layer RPC connect fail";
            if (m_pClient->has_connected()) {
                qDebug() << "layer RPC connect success";

                break;
            } else {
                std::this_thread::sleep_for(std::chrono::milliseconds(500));
                qDebug() << "layer RPC connect fail";
            }
        }
    }).detach();
}

rest_rpc::rpc_client *RPCClient::getSocketObject()
{
    return m_pClient;
}

layer/Sources/rpc/RPCServer.cpp

#include "RPCServer.h"
#include "rpc/MessageTip.h"

RPCServer::RPCServer(QObject *parent) : QObject(parent)
{
    QThread::create([&] {
        rpc_server server(9000, std::thread::hardware_concurrency());

        server.register_handler("MessageTip::layervalueChanged", &RPCServer::layervalueChanged, this);
        server.register_handler("MessageTip::layerstringChanged", &RPCServer::layerstringChanged, this);

        server.run();
    })->start();
    qDebug() << "start rpc server";
}

void RPCServer::layervalueChanged(rpc_conn conn , int value)
{
    //todo
    MessageTip::setApplyvalue(value);
    qDebug() << "APPLY SEND :" << value;
}

void RPCServer::layerstringChanged(rpc_conn conn , std::string value)
{
    //todo
    MessageTip::setApplystring(value);
    qDebug() << "APPLY SEND :" << QString::fromStdString(value);
}

layer/Sources/main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include "qdebug.h"
#include "mainwidget.h"

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

    QGuiApplication app(argc, argv);

//    QQmlApplicationEngine engine;
//    const QUrl url(QStringLiteral("qrc:/main.qml"));
//    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
//    &app, [url](QObject * obj, const QUrl & objUrl) {
//        if (!obj && url == objUrl) {
//            QCoreApplication::exit(-1);
//        }
//    }, Qt::QueuedConnection);
//    engine.load(url);

    mainwidget mainwidget;

    return app.exec();
}

layer/Sources/mainwidget.cpp

#include "mainwidget.h"
#include "rpc/RPCClient.h"

mainwidget::mainwidget()
{
    QQmlApplicationEngine *m_pEngine = new QQmlApplicationEngine;
    QQmlComponent component(m_pEngine, QUrl(QStringLiteral("qrc:/main.qml")));
    QObject *mainObject = component.create();
    if (mainObject == nullptr) {
        qDebug() << "mainObject fail";
        return;
    }

    m_pRPCServer = new RPCServer();
    RPCClient::get_instance()->tryConnect();
}

layer/main.qml

import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12

Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello layer")

    Column{
        anchors.fill: parent
        spacing: 20
        Button{
            width: 140
            height: 50

            text: "layer +"
        }

        Button{
            width: 140
            height: 50

            text: "layer -"
        }
    }
}

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

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

相关文章

GEE学习笔记 八十四:【GEE之Python版教程十四】矢量数据(ee.feature)

上一节讲了几何图形Geometry&#xff0c;这一节讲矢量数据&#xff08;ee.feature&#xff09;&#xff0c;它的构成也就是几何图形以及属性字典。 1、API定义 首先看一下GEE的python版API&#xff08;Welcome to GEE-Python-API’s documentation! — GEE-Python-API 1.0 do…

【论文】智能隧道检测车的现状及改进策略

本文转载自《智慧城轨》2022年第11期 作者&#xff1a;黄丹樱1,韦强1,朱椰毅2,范骁1,林浩立1 单位&#xff1a;1 浙江师范大学工学院&#xff1b;2 浙江金温铁道开发有限公司 声明&#xff1a;本文仅用于学术分享&#xff0c;不做商业用途&#xff0c;如有侵权&#xff0c;联…

从实现到原理,聊聊Java中的SPI动态扩展

原创&#xff1a;微信公众号 码农参上&#xff0c;欢迎分享&#xff0c;转载请保留出处。 八股文背多了&#xff0c;相信大家都听说过一个词&#xff0c;SPI扩展。 有的面试官就很喜欢问这个问题&#xff0c;SpringBoot的自动装配是如何实现的&#xff1f; 基本上&#xff0c…

Redis第二讲

二、Redis02 2.1 发布和订阅 Redis 发布订阅 (pub/sub) 是一种消息通信模式&#xff1a;发送者 (pub) 发送消息&#xff0c;订阅者 (sub) 接收消息。 Redis 客户端可以订阅任意数量的频道。 发布订阅的实现 1、打开一个客户端订阅channel1 127.0.0.1:6379> subscribe ch…

红黑树的原理+实现

文章目录红黑树定义性质红黑树的插入动态效果演示代码测试红黑树红黑树 定义 红黑树是一个近似平衡的搜索树&#xff0c;关于近似平衡主要体现在最长路径小于最短路径的两倍&#xff08;我认为这是红黑树核心原则&#xff09;&#xff0c;为了达到这个原则&#xff0c;红黑树所…

LeetCode刷题--- 面试题 01.07. 旋转矩阵(原地旋转+翻转替旋转)

&#x1f48c; 所属专栏&#xff1a;【LeetCode题解&#xff08;持续更新中&#xff09;】 &#x1f600; 作  者&#xff1a;我是夜阑的狗&#x1f436; &#x1f680; 个人简介&#xff1a;一个正在努力学技术的CV工程师&#xff0c;专注基础和实战分享 &#xff0c;…

【C++之容器篇】二叉搜索树的理论与使用

目录前言一、二叉搜索树的概念二、二叉搜素树的模拟实现&#xff08;增删查非递归实现&#xff09;1. 二叉搜素树的结点2. 二叉搜索树的实现&#xff08;1&#xff09;. 二叉搜索树的基本结构&#xff08;2&#xff09;构造函数&#xff08;3&#xff09;查找函数&#xff08;4…

1225057-68-0,Alkyne PEG4 TAMRA-5,四甲基罗丹明-四聚乙二醇-炔基TAMRA红色荧光染料连接剂

中英文别名&#xff1a;CAS号&#xff1a;1225057-68-0 | 英文名&#xff1a;5-TAMRA-PEG4-Alkyne |中文名&#xff1a;5-四甲基罗丹明-四聚乙二醇-炔基物理参数&#xff1a;CASNumber&#xff1a;1225057-68-0Molecular formula&#xff1a;C36H41N3O8Molecular weight&#x…

P16 激活函数与Loss 的梯度

参考&#xff1a;https://www.ngui.cc/el/507608.html?actiononClick这里面简单回顾一下PyTorch 里面的两个常用的梯度自动计算的APIautoGrad 和 Backward, 最后结合 softmax 简单介绍一下一下应用场景。目录&#xff1a;1 autoGrad2 Backward3 softmax一 autoGrad输入 x输出损…

buu [UTCTF2020]basic-crypto 1

题目描述&#xff1a; 01010101 01101000 00101101 01101111 01101000 00101100 00100000 01101100 01101111 01101111 01101011 01110011 00100000 01101100 01101001 01101011 01100101 00100000 01110111 01100101 00100000 01101000 01100001 01110110 01100101 00100000 0…

【Kubernetes】【七】命令式对象配置和声明式对象配置

命令式对象配置 命令式对象配置就是使用命令配合配置文件一起来操作kubernetes资源。 1&#xff09; 创建一个nginxpod.yaml&#xff0c;内容如下&#xff1a; apiVersion: v1 kind: Namespace metadata:name: dev---apiVersion: v1 kind: Pod metadata:name: nginxpodnames…

调用Windows安全中心实现登录验证

文章目录运行效果用到的运行库代码实现使用日志Win10 Flat风格XP风格总结运行效果 输入用户名和密码点击确定后获取到的信息&#xff1a; 用到的运行库 NuGet搜索安装即可 Kang.ExtendMethodKang.ExtendMethod.Log https://gitee.com/haozekang/kang Vanara.PInvoke https:…

安全算法 - 国密算法

国密即国家密码局认定的国产密码算法。主要有SM1&#xff0c;SM2&#xff0c;SM3&#xff0c;SM4&#xff0c;SM7, SM9。国密算法分类国家标准官方网站如下&#xff1a;http://openstd.samr.gov.cn/bzgk/gb/SM1 为对称加密。其加密强度与AES相当。该算法不公开&#xff0c;调用…

Nacos——配置管理基础应用

目录 一、快速入门 1.1 发布配置 1.2 nacos client远程获取配置 1.2.1 导入坐标 1.2.2 程序代码 二、Nacos配置管理基础应用 2.1 Nacos配置管理模型 2.1.2 配置集(Data Id) 2.1.3 配置项 2.1.4 配置分组 (Group) 2.1.5 命名空间(Namespace) 2.1.6 最佳实践&#xff0…

Worok:专门针对亚洲实体的网络间谍组织

ESET 的研究人员发现了一个全新的攻击组织 Worok&#xff0c;该组织自动 2020 年就一直处于活跃状态。Worok 使用的工具集包括一个 C 编写的加载程序 CLRLoad、一个 PowerShell 编写的后门 PowHeartBeat 和一个 C# 编写的加载程序 PNGLoad&#xff0c;攻击者使用隐写术来提取隐…

PPT与Inkscape自定义色板

PPT与Inkscape自定义色板简述 本文主要分享了PPT与Inkscape中自定义色板功能&#xff0c;以满足个性化配色需求。此外&#xff0c;文末分享了常见的配色网站和图片网站&#xff0c;前者可以满足配色需求&#xff0c;后者可以满足配图需求。 PPT自定义色板 在常见的办公三件套中…

pycharm远程连接服务器,并单步调试服务器上的代码

每天都有不同的朋友来Push我 那如果比较健忘的话&#xff0c;为啥不问一下chatGPT呢 问题的缘由在我想在本地单步调试代码。。。 我的代码完全在云端服务器的&#xff0c;还有数据集都是&#xff0c;但实际上本地代码可以通过pycharm给他传上去。 但是在后面配置的时候需要两…

高密度部署,基于动态库的尝试,rust动态调库

目录前言faas特点方案思考实践制作动态库调用动态库尾语前言 最近在搞faas平台&#xff0c;也试了各大云厂商的产品&#xff0c;效果都不是很理想。和我心目中的faas想去甚远。  和小伙伴们吹完牛逼&#xff0c;心有所感&#xff0c;写下这篇文章&#xff0c;时间跨度较长&…

「AI人工智能」Node.js如何接入OpenAI开发

文章目录前言一、创建OpenAI账号二、安装axios 库三、导入 axios 库四、调用 OpenAI API五、测试 OpenAI API前言 本文主要介绍如何将 Node.js 应用程序与 OpenAI 集成&#xff0c;可以使用 OpenAI API。 一、创建OpenAI账号 创建一个 OpenAI 帐户并注册 API 密钥。你可以在 …

Linux系统一键检测和加固脚本

主要是为了Linux系统的安全&#xff0c;通过脚本对Linux系统进行一键检测和一键加固。 Check_Script #包含2个文件 CentOS_Check_Script.sh README.txt 操作说明 #执行CentOS-Check_Script.sh脚本文件进行检查,命令格式如下 sudo sh CentOS_Check_Script.sh | tee check_da…