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

QT项目_RPC(进程间通讯)

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 = subdirsSUBDIRS += \apply \layer

apply/apply.pro

QT += quick \widgetsCONFIG += 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.0SOURCES += \main.cpp \mainwidget.cpp \rpc/MessageTip.cpp \rpc/RPCClient.cpp \rpc/RPCServer.cppRESOURCES += 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/msgpackHEADERS += \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)
{//todoqDebug() << "apply recv :" << value;
}void RPCServer::setApplystring(rpc_conn conn , std::string value)
{//todoqDebug() << "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.12Window {visible: truewidth: 640height: 480objectName: "apply_window"title: qsTr("Hello apply")signal window_interface(bool enable)Column{anchors.fill: parentspacing: 20Button{width: 140height: 50text: "开启界面2"onClicked: {window_interface(true)}}Mybutton{width: 140height: 300}}
}

apply/Mybutton.qml

import QtQuick 2.0
import QtQuick.Controls 2.12Item {objectName: "mybutton"signal applyvalueChanged(int value)signal applystringChanged(string value)Column{spacing: 10Button{objectName: "button"width: 140height: 50text: "send1"onClicked: {applyvalueChanged(1)}}Button{width: 140height: 50text: "send2"onClicked: {applyvalueChanged(2)}}Button{width: 140height: 50text: "验证string"onClicked: {applystringChanged("{\"name\":\"lili\",\"age\":24,\"class\":6}")}}}
}

layer.pro

QT += quick
QT += widgetsCONFIG += 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.0SOURCES += \main.cpp \mainwidget.cpp \rpc/MessageTip.cpp \rpc/RPCClient.cpp \rpc/RPCServer.cppRESOURCES += 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/msgpackHEADERS += \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);
//#elsem_pClient = new rest_rpc::rpc_client("127.0.0.1", 9001);
//#endifm_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)
{//todoMessageTip::setApplyvalue(value);qDebug() << "APPLY SEND :" << value;
}void RPCServer::layerstringChanged(rpc_conn conn , std::string value)
{//todoMessageTip::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.12Window {visible: truewidth: 640height: 480title: qsTr("Hello layer")Column{anchors.fill: parentspacing: 20Button{width: 140height: 50text: "layer +"}Button{width: 140height: 50text: "layer -"}}
}

相关文章:

QT项目_RPC(进程间通讯)

QT项目_RPC(进程间通讯) 前言&#xff1a; 两个进程间通信、或是说两个应用程序之间通讯。实际情况是在QT开发的一个项目中&#xff0c;里面包含两个子程序&#xff0c;子程序有单独的界面和应用逻辑&#xff0c;这两个子程序跑起来之后需要一些数据的交互&#xff0c;例如&…...

移动硬盘文件丢失怎么恢复?

在我们的日常工作、学习和生活都离不开各种数据。每天都会接收或处理各种数据&#xff0c;尤其是做设计、自媒体、多媒体设计的人。移动硬盘成为我们常备的存储工具&#xff0c;但有使用就会伴随着意外情况的发生&#xff0c;这将导致移动硬盘上数据的丢失&#xff0c;比如误删…...

什么是同步整流和异步整流

在设计降压型DCDC电路的时候&#xff0c;经常会听到同步整流&#xff08;synchronous&#xff09;和异步整流&#xff08;asynchronous&#xff09;。那么什么是同步整流&#xff0c;什么是异步整流呢从这两种电路的拓扑来看&#xff0c;异步整流型外围有一个续流二极管&#x…...

关于PYTHON Enclosing 的一个小问题

问题分析 以下是一段每隔半小时重复执行测试用例的脚本&#xff0c;func是传入的测试函数&#xff0c;在执行func前后&#xff0c;会打印操作次数 def repeat(func, action):try:log.info(u******开始并发%s****** % action)thread_list []for i in range(repeat_count):def…...

LabVIEW错误-2147220623:最大内存块属性不存在

LabVIEW错误-2147220623&#xff1a;最大内存块属性不存在在使用NI Linux实时操作系统目标中&#xff0c;使用系统属性节点和分布式系统管理器&#xff08;DSM&#xff09;&#xff0c;但遇到一些问题&#xff1a;它未正确报告系统上的可用物理内存量。在NI Linux实时系统上出现…...

图的总复习

一、图的定义Graph 图是由顶点vertex集合及顶点间关系集合组成的一种数据结构&#xff1a; 顶点的集合 和 边的集合 二、无向图 用&#xff08;x,y&#xff09;表示两个顶点x和y之间的一条边&#xff08;edge&#xff09; 边是无方向的 N{V&#xff0c;E}&#xff0c;V{0…...

测试流程记录

1&#xff0c;需求评审 2&#xff0c;技术方案评审 3&#xff0c;编写测试用例 编写需求分析 编写测试用例 编写冒烟case 4&#xff0c;用例评审 5&#xff0c;提测 提测前给开发执行冒烟case 6&#xff0c;测试 测试完成前约产品验收时间 7&#xff0c;验收 跟进验收问题…...

Mysql主从架构与实例

mysql的主从架构 MySQL主从架构是一种常见的数据库高可用性解决方案&#xff0c;它通常由一个主数据库和多个从数据库组成。主数据库用于处理写入请求和读取请求&#xff0c;从数据库则用于处理只读请求。 在主从架构中&#xff0c;主数据库记录所有数据更改并将这些更改同步…...

webpack(高级)--Tapable

webpack 我们直到webpack中有两个非常重要的类Compiler和Compilation 他们通过注入插件的方式 来监听webpack的所有声明周期 插件的注入是通过创建Tapable库中的各种Hook的实例来得到 Tapable Tapable中的Hook分为同步与异步 同步 SyncHook SyncBailHook SyncWaterfallHook…...

Python常见类型转换合集

近期在工作中常常接触到各种转换&#xff0c;如字符串转byte&#xff0c;byte转字符串&#xff0c;还有byte数组转成报文能接纳的格式&#xff08;bin格式的十六进制&#xff09;。故有必要系统的总结一下Python中常见的类型转换。 一&#xff1a;常见类型的概念 类型举例说明…...

知识点(1)

什么是跨域请求&#xff1f; 当前发起请求的域与该请求指向的资源所在的域不一样&#xff0c;凡是发送请求的url的协议、域名、端口号三者之间任意一者与当前页面地址不同的请求。这里的域指的是&#xff1a;我们认为若协议域名端口号均相同&#xff0c;那么就是同域。 get和…...

Tomcat源码分析-启动分析(三) Catalina启动

在上一篇文章中&#xff0c;我们分析了tomcat的初始化过程&#xff0c;是由Bootstrap反射调用Catalina的load方法完成tomcat的初始化&#xff0c;包括server.xml的解析、实例化各大组件、初始化组件等逻辑。那么tomcat又是如何启动webapp应用&#xff0c;又是如何加载应用程序的…...

程序员必备的软技能-金字塔原理拆解

前言 日常工作中&#xff0c;常常因为思维、表达方式不对产生不想要的结果&#xff1a; 写了一个小时的周报&#xff0c;领导却不满意&#xff1f;跟团队讲了半天自己的想法&#xff0c;可别人就是没理解&#xff1f;看了很多知识、信息&#xff0c;却一点也没记住&#xff1…...

基金详细介绍

投资回报率 利润 / 投资总额&#xff08;第一次投资回报率 5%&#xff09; 关注南方理财 60 天债券 B&#xff08;202306&#xff09;万元收益 50—60 元 购基七步曲&#xff1a; 风险测试基本知识交易指南查看业绩了解评级在线下单赎回 基金类型&#xff1a; 积极成长型基金…...

媒体邀约之企业如何加强品牌的宣传力度

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。胡老师分享了许多媒体传播方面的经验&#xff0c;今天就跟大家分享下我对企业宣传方面的看法。企业如何加强品牌的宣传力度&#xff1a;1&#xff0c;网络宣传在社交媒体上建立企业账户&am…...

【SpringBoot】75、SpringBoot中使用spring-retry轻松解决重试

在日常开发过程中&#xff0c;难免会与第三方接口发生交互&#xff0c;例如&#xff1a;短信发送、远程服务调用、争抢锁等场景&#xff0c;当正常调用发生异常时&#xff0c;例如&#xff1a;网络抖动&#xff0c;这些间歇性的异常在一段时候之后会自行恢复&#xff0c;程序为…...

网络工程师必知的几个问题

路由器问题&#xff1a; 1、什么时候使用多路由协议&#xff1f; 当两种不同的路由协议要交换路由信息时&#xff0c;就要用到多路由协议。当然&#xff0c;路由再分配也可以交换路由信息。下列情况不必使用多路由协议&#xff1a; 从老版本的内部网关协议&#xff08; interi…...

【仓库管理】搭建 Maven 私服之一--Nexus仓库(Repository)管理软件

文章目录Nexus是什么Nexus下载和安装1. 进入 Nexus 2.x 下载页面&#xff0c;根据本机操作系统&#xff0c;选择对应的版本进行下载&#xff0c;如下图所示。2. 将下载 Nexus 安装包解压到本地磁盘&#xff0c;可获得 nexus-2.14.20-02 和 sonatype-work 2 个目录&#xff0c;如…...

凹凸贴图(Bump Mapping)

凹凸贴图是什么&#xff1f; 我们首先来看low-poly&#xff08;多边形数较少&#xff09;mesh和high-poly&#xff08;多边形数量较多&#xff09;mesh之间的不同。首先&#xff0c;最明显的不同就是high-poly能够表现出更多细节&#xff0c;但high-poly有比较大的性能开销。有…...

文华财经期货指标公式量化策略分析软件,多空共振信号准确率高的公式源码

期货指标公式信号本身就有滞后性&#xff0c;周期越大&#xff0c;滞后性越久。指标公式不是100%稳赚的工具&#xff0c;只是在合适的时候让我们理性看待行情&#xff0c;减少逆势操作。 多空量化三维系统是一款通过数学分析、挖掘价格运动规律&#xff0c;对历史价格走势、趋势…...

安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件

在选煤厂、化工厂、钢铁厂等过程生产型企业&#xff0c;其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进&#xff0c;需提前预防假检、错检、漏检&#xff0c;推动智慧生产运维系统数据的流动和现场赋能应用。同时&#xff0c;…...

【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)

升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点&#xff0c;但无自动故障转移能力&#xff0c;Master宕机后需人工切换&#xff0c;期间消息可能无法读取。Slave仅存储数据&#xff0c;无法主动升级为Master响应请求&#xff…...

网络编程(UDP编程)

思维导图 UDP基础编程&#xff08;单播&#xff09; 1.流程图 服务器&#xff1a;短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…...

代理篇12|深入理解 Vite中的Proxy接口代理配置

在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...

初学 pytest 记录

安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...

安卓基础(aar)

重新设置java21的环境&#xff0c;临时设置 $env:JAVA_HOME "D:\Android Studio\jbr" 查看当前环境变量 JAVA_HOME 的值 echo $env:JAVA_HOME 构建ARR文件 ./gradlew :private-lib:assembleRelease 目录是这样的&#xff1a; MyApp/ ├── app/ …...

虚拟电厂发展三大趋势:市场化、技术主导、车网互联

市场化&#xff1a;从政策驱动到多元盈利 政策全面赋能 2025年4月&#xff0c;国家发改委、能源局发布《关于加快推进虚拟电厂发展的指导意见》&#xff0c;首次明确虚拟电厂为“独立市场主体”&#xff0c;提出硬性目标&#xff1a;2027年全国调节能力≥2000万千瓦&#xff0…...

【Nginx】使用 Nginx+Lua 实现基于 IP 的访问频率限制

使用 NginxLua 实现基于 IP 的访问频率限制 在高并发场景下&#xff0c;限制某个 IP 的访问频率是非常重要的&#xff0c;可以有效防止恶意攻击或错误配置导致的服务宕机。以下是一个详细的实现方案&#xff0c;使用 Nginx 和 Lua 脚本结合 Redis 来实现基于 IP 的访问频率限制…...

三分算法与DeepSeek辅助证明是单峰函数

前置 单峰函数有唯一的最大值&#xff0c;最大值左侧的数值严格单调递增&#xff0c;最大值右侧的数值严格单调递减。 单谷函数有唯一的最小值&#xff0c;最小值左侧的数值严格单调递减&#xff0c;最小值右侧的数值严格单调递增。 三分的本质 三分和二分一样都是通过不断缩…...

「全栈技术解析」推客小程序系统开发:从架构设计到裂变增长的完整解决方案

在移动互联网营销竞争白热化的当下&#xff0c;推客小程序系统凭借其裂变传播、精准营销等特性&#xff0c;成为企业抢占市场的利器。本文将深度解析推客小程序系统开发的核心技术与实现路径&#xff0c;助力开发者打造具有市场竞争力的营销工具。​ 一、系统核心功能架构&…...