OpenHarmony-6.IPC/RPC组件

  • IPC/RPC组件机制

1.基本概念

  IPC:设备内的进程间通信(Inter-Process Communication)。

  RPC:设备间的进程间通信(Remote Procedure Call)。

  IPC/RPC用于实现跨进程通信,不同的是前者使用Binder驱动,用于设备内的跨进程通信,后者使用软总线驱动,用于跨设备跨进程通信。需要跨进程通信的原因是因为每个进程都有自己独立的资源和内存空间,其他进程不能随意访问不同进程的内存和资源,IPC/RPC便是为了突破这一点。

  Client-Server 软件模型外加 Interface 接口共同组成了 OpenHarmony 诸多子系统的架构,使其系统的稳定性、扩展性以及进程通信能力得到加强。子系统中均可见到 Interface 接口目录、Framework 客户端目录以及 Service 服务端目录,工作重点一般集中在 Service 服务端,如下图所示:
在这里插入图片描述

1.1.实现原理

  IPC和RPC通常采用客户端-服务端(Client-Server)模型,在使用时,请求Client端进程可获取Server端所在进程的代理(Proxy),并通过此代理读写数据来实现进程间的数据通信,更具体的讲,首先客户端会建立一个服务端的代理对象,这个代理对象具备和服务端一样的功能,若想访问服务端中的某一个方法,只需访问代理对象中对应的方法即可,代理对象会将请求发送给服务端;然后服务端处理接受到的请求,处理完之后通过驱动返回处理结果给代理对象;最后代理对象将请求结果进一步返回给客户端。

  如下图所示: 通常,Stub会先注册系统能力(System Ability)到系统能力管理者(System Ability Manager,缩写SAMgr)中,SAMgr负责管理这些SA并向Client提供相关的接口。Client要和某个具体的SA通信,必须先从SAMgr中获取该SA的代理Proxy对象,然后使用代理Proxy对象和SA通信。在整个通信过程中,如果使用的是IPC通信,则依赖的是Binder驱动,使用的是RPC通信,则依赖的是软总线驱动。

说明: 以下为IPC与RPC的典型使用场景:

  • IPC典型使用场景在后台服务,应用的后台服务通过IPC机制提供跨进程的服务调用能力。
  • RPC典型使用场景在多端协同,多端协同通过RPC机制提供远端接口调用与数据传递能力。

  IPC通信机制架构图:
在这里插入图片描述

  目录结构:

/foundation/communication/ipc
├── interfaces        # 对外接口存放目录
│   └── innerkits     # 对内部子系统暴露的头文件存放目录
│       ├── ipc_core     # ipc 接口存放目录
│       └── libdbinder   # dbinder 接口存放目录
├── ipc            # ipc 框架代码
│   ├── native     # ipc native 实现存放目录
│       ├── src    # ipc native 源代码存放目录
│       └── test   # ipc native 单元测试用例存放目录
│   └── test       # ipc native 模块测试用例存放目录
├── service        # dbinder 实现存放目录
│   └── dbinder    # dbinder 源代码存放目录

1.2.Binder机制

  Binder机制通常采用客户端-服务器(Client-Server)模型,服务请求方(Client)可获取服务提供方(Server)的代理 (Proxy),并通过此代理读写数据来实现进程间的数据通信。通常,系统能力(SystemAbility)Server侧会先注册到系统能力管理者(System Ability Manager,缩写SAMgr)中,SAMgr负责管理这些SA并向Client提供相关的接口(添加,查询,获取,删除等)。Client要和某个具体的SA通信,必须先从SAMgr中获取该SA的代理,然后使用代理和SA通信。

注:SAMgr本身也是IPC的Server端,Client通过SAMgr的代理,调用SAMgr的接口。

  Binder机制架构图:
在这里插入图片描述

2.系统服务管理子系统

  系统服务管理子系统由两部分构成:

  • 系统服务框架组件(safwk):定义了SystemAbility的实现方法,并提供启动、发布等接口实现。
  • 系统服务管理组件(samgr): 提供系统服务注册、查询等功能。

  系统服务管理架构图如下:
在这里插入图片描述
  代码目录:

/foundation/systemabilitymgr
│── safwk               # 组件目录
│  ├── bundle.json      # 组件描述及编译脚本
│  ├── etc              # 配置文件
│  ├── interfaces       # 对外接口目录
│  ├── services         # 框架实现
│  ├── test             # 测试用例
├── samgr
│   ├── bundle.json  # 部件描述及编译文件
│   ├── frameworks   # 框架实现存在目录
│   ├── interfaces   # 接口目录
│   ├── services     # 组件服务端目录
│   ├── test         # 测试代码存放目录
│   ├── utils        # 工具类目录

2.1.系统服务框架组件

  SystemAbility实现一般采用XXX.cfg + saId.xml + libXXX.z.so的方式由init进程解析对应的XXX.cfg文件拉起SystemAbility所依赖的进程。(注:多个系统服务可能跑在同一个进程里。比如AbilityManagerService、BatteryService、WindowManagerService都在foundation进程,MMIService在独立的进程multimodalinput中。)

  SystemAbility类图如下:
在这里插入图片描述
备注:

SystemAbility子类需要重写OnStart()和OnStop()方法,并且在OnStart()方法中调用Publish(sptr systemAbility)方法把系统服务发布出去。

2.2.系统服务实现步骤

  以AbilityManagerService为例说明SystemAbility的实现。

2.2.1.定义IPC对外接口IXXX

  定义该服务对外提供的能力集合函数,统一继承IPC接口类IRemoteBroker;同时声明该IPC对外接口唯一标识符DECLARE_INTERFACE_DESCRIPTOR(XXX);该标识符用于IPC通信的校验等目的。

foundation\ability\ability_runtime\interfaces\inner_api\ability_manager\include\ability_manager_interface.h:
  69 class IAbilityManager : public OHOS::IRemoteBroker {
  70 public:
  71     DECLARE_INTERFACE_DESCRIPTOR(u"ohos.aafwk.AbilityManager")
  72
  73     /**
  74      * StartAbility with want, send want to ability manager service.
  75      *
  76      * @param want, the want of the ability to start.
  77      * @param userId, Designation User ID.
  78      * @param requestCode, Ability request code.
  79      * @return Returns ERR_OK on success, others on failure.
  80      */
  81     virtual int StartAbility(
  82         const Want &want,
  83         int32_t userId = DEFAULT_INVAL_VALUE,
  84         int requestCode = DEFAULT_INVAL_VALUE) = 0;
  85
  86   ...
  87 }
  • 定义客户端代码XXXProxy
foundation\ability\ability_runtime\services\abilitymgr\include\ability_manager_proxy.h:
 30 class AbilityManagerProxy : public IRemoteProxy<IAbilityManager> {
 31 public:
 32     explicit AbilityManagerProxy(const sptr<IRemoteObject> &impl) : IRemoteProxy<IAbilityManager>(impl)
 33     {}
 34
 35     virtual ~AbilityManagerProxy()
 36     {}
 37
 46     virtual int StartAbility(
 47         const Want &want,
 48         int32_t userId = DEFAULT_INVAL_VALUE,
 49         int requestCode = DEFAULT_INVAL_VALUE) override;
 50
 51    ...
 52 }
 foundation\ability\ability_runtime\services\abilitymgr\src\ability_manager_proxy.cpp
  42 int AbilityManagerProxy::StartAbility(const Want &want, int32_t userId, int requestCode)
  43 {
  44     int error;
  45     MessageParcel data;
  46     MessageParcel reply;
  47     MessageOption option;
  48
  49     if (!WriteInterfaceToken(data)) {
  50         return INNER_ERR;
  51     }
  52     if (!data.WriteParcelable(&want)) {
  53         HILOG_ERROR("want write failed.");
  54         return INNER_ERR;
  55     }
  56
  57     if (!data.WriteInt32(userId)) {
  58         HILOG_ERROR("userId write failed.");
  59         return INNER_ERR;
  60     }
  61
  62     if (!data.WriteInt32(requestCode)) {
  63         HILOG_ERROR("requestCode write failed.");
  64         return INNER_ERR;
  65     }
  66
  67     error = SendRequest(AbilityManagerInterfaceCode::START_ABILITY, data, reply, option);
  72     return reply.ReadInt32();
  73 }

  AbilityManagerProxy::StartAbility()实现代码中会调用Remote()->SendRequest(IAbilityManager::START_ABILITY, data, reply, option);把消息码和数据发送给服务端。

-定义服务端代码XXXStub

 foundation\ability\ability_runtime\services\abilitymgr\include\ability_manager_stub.h
 34 class AbilityManagerStub : public IRemoteStub<IAbilityManager> {
 35 public:
 36     AbilityManagerStub();
 37     ~AbilityManagerStub();
 38     virtual int OnRemoteRequest(
 39         uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override;
 40
 48     virtual int DoAbilityForeground(const sptr<IRemoteObject> &token, uint32_t flag) override;
 49
 50  ...
 51 }
 foundation\ability\ability_runtime\services\abilitymgr\src\ability_manager_stub.cpp:
 332 int AbilityManagerStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)
 333 {
 334     std::u16string abilityDescriptor = AbilityManagerStub::GetDescriptor();
 335     std::u16string remoteDescriptor = data.ReadInterfaceToken();
 336     if (abilityDescriptor != remoteDescriptor && extensionDescriptor != remoteDescriptor) {
 337         HILOG_ERROR("local descriptor is not equal to remote");
 338         return ERR_INVALID_STATE;
 339     }
 340
 341     auto itFunc = requestFuncMap_.find(code);
 342     if (itFunc != requestFuncMap_.end()) {
 343         auto requestFunc = itFunc->second;
 344         if (requestFunc != nullptr) {
 345             return (this->*requestFunc)(data, reply);
 346         }
 347     }
 348     HILOG_WARN("default case, need check.");
 349     return IPCObjectStub::OnRemoteRequest(code, data, reply, option);
 350 }

  requestFuncMap_[START_ABILITY] = &AbilityManagerStub::StartAbilityInner。消息码START_ABILITY对应的函数为AbilityManagerStub::StartAbilityInner。

 600 int AbilityManagerStub::StartAbilityInner(MessageParcel &data, MessageParcel &reply)
 601 {
 602     Want *want = data.ReadParcelable<Want>();
 603     if (want == nullptr) {
 604         HILOG_ERROR("want is nullptr");
 605         return ERR_INVALID_VALUE;
 606     }
 607     int32_t userId = data.ReadInt32();
 608     int requestCode = data.ReadInt32();
 609     int32_t result = StartAbility(*want, userId, requestCode);
 610     reply.WriteInt32(result);
 611     delete want;
 612     return NO_ERROR;
 613 }

  StartAbility()的实现在AbilityManagerStub的实现类AbilityManagerService中。

  • SystemAbility的实现类
 foundation\ability\ability_runtime\services\abilitymgr\include\ability_manager_service.h
 76 class AbilityManagerService : public SystemAbility,
  77                               public AbilityManagerStub,
  78                               public AppStateCallback,
  79                               public std::enable_shared_from_this<AbilityManagerService> {
  80     DECLARE_DELAYED_SINGLETON(AbilityManagerService)
  81     DECLEAR_SYSTEM_ABILITY(AbilityManagerService)
  82 public:
  83     void OnStart() override;
  84     void OnStop() override;
  85
  86     virtual void OnAddSystemAbility(int32_t systemAbilityId, const std::string& deviceId) override;
  87
  88     virtual void OnRemoveSystemAbility(int32_t systemAbilityId, const std::string& deviceId) override;
  89
  90     ServiceRunningState QueryServiceState() const;
  91
 100     virtual int StartAbility(
 101         const Want &want, int32_t userId = DEFAULT_INVAL_VALUE, int requestCode = DEFAULT_INVAL_VALUE) override;
 102    ...
 103 }

  AbilityManagerService同时继承了SystemAbility和AbilityManagerStub。在重写的SystemAbility的接口函数OnStart()中,调用Publish(instance_)把自己发布出去。

 foundation/ability/ability_runtime/services/abilitymgr/src/ability_manager_service.cpp
  268 void AbilityManagerService::OnStart()
 269 {
 270     if (state_ == ServiceRunningState::STATE_RUNNING) {
 271         HILOG_INFO("AMS has already started.");
 272         return;
 273     }
 274     HILOG_INFO("AMS starting.");
 275     if (!Init()) {
 276         HILOG_ERROR("Failed to init AMS.");
 277         return;
 278     }
 279     state_ = ServiceRunningState::STATE_RUNNING;
 280     /* Publish service maybe failed, so we need call this function at the last,
 281      * so it can't affect the TDD test program */
 282     instance_ = DelayedSingleton<AbilityManagerService>::GetInstance().get();
 287     bool ret = Publish(instance_);                       
 292
 293     SetParameter(BOOTEVENT_A // In namespace OHOS true");
 294     WatchParameter(BOOTEVENT namespace AAFwk {}   ), AAFwk::ApplicationUtil::AppFwkBootEventCallback, nullptr);
 295     AddSystemAbilityListener(BACKGROUND_TASK_MANAGER_SERVICE_ID);
 296     AddSystemAbilityListener(DISTRIBUTED_SCHED_SA_ID);
 297     AddSystemAbilityListener(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
 298     HILOG_INFO("AMS start success.");
 299 }

注:在实现SystemAbility的时候,必须调用宏REGISTER_SYSTEM_ABILITY_BY_ID或者SystemAbility::MakeAndRegisterAbility()把SystemAbility注册到LocalAbilityManager中。可参考如下代码:
const bool REGISTER_RESULT = SystemAbility::MakeAndRegisterAbility(DelayedSingleton::GetInstance().get());

  • SystemAbility配置

  以c++实现的SA必须配置相关SystemAbility的profile配置文件才会完成SA的自动加载注册逻辑,否则没有编写配置文件的SystemAbility不会完成自动加载注册。配置方法如下:
  在子系统的根目录新建一个以sa_profile为名的文件夹,然后在此文件夹中新建两个文件:一个以saId为前缀的xml文件,另外一个为BUILD.gn文件。比如AbilityManagerService,saId为ABILITY_MGR_SERVICE_ID(即180),对应的配置文件为180.xml。内容如下:

foundation/ability/ability_runtime/services/sa_profile/BUILD.gn:
14 import("//build/ohos/sa_profile/sa_profile.gni")
 15
 16 ohos_sa_profile("ams_sa_profile") {
 17   sources = [
 18     "180.json",
 19     "182.json",
 20     "183.json",
 21     "184.json",
 22     "501.json",
 23   ]
 24
 25   part_name = "ability_runtime"
 26 }

描述说明:

  • part_name为相应部件名称;
  • sources表示当前子系统需要配置的SystemAbility列表,可支持配置多个SystemAbility。
  foundation/ability/ability_runtime/services/sa_profile/180.json:
  1 {
  2     "process": "foundation",
  3     "systemability": [
  4         {
  5             "name": 180,
  6             "libpath": "libabilityms.z.so",
  7             "run-on-create": true,
  8             "distributed": false,
  9             "dump_level": 1
 10         }
 11     ]
 12 }

描述说明:

  • 进程名字:该SystemAbility要运行的进程空间,此字段是必填选项。即AbilityManagerService跑在foundation进程中。
  • 一个SystemAbility配置文件只能配置一个SystemAbility节点,配置多个会导致编译失败。
  • SystemAbility的name为对应的saId必须与代码中注册的saId保持一致,必配项。
  • libpath为SystemAbility的加载路径,必配项。
  • run-on-create:true表示进程启动后即向samgr组件注册该SystemAbility;false表示按需启动,即在其他模块访问到该SystemAbility时启动,必配项。
  • distributed:true表示该SystemAbility为分布式SystemAbility,支持跨设备访问;false表示只有本地跨进程访问。
  • bootphase:可不设置;可以设置的值有三种:BootStartPhase、CoreStartPhase、OtherStartPhase(默认类型),三种优先级依次降低,在同一个进程中,会优先拉起注册配置BootStartPhase的SystemAbility,然后是配置了CoreStartPhase的SystemAbility,最后是OtherStartPhase;当高优先级的SystemAbility全部启动注册完毕才会启动下一级的SystemAbility的注册启动。
  • dump-level:表示systemdumper支持的level等级,默认配置1。

  以上步骤完成后,全量编译代码后会在out路径下生成一个以进程名为前缀的xml文件(比如foundation.xml),路径为:out\…\system\profile\foundation.xml。该文件整合了所有需要在该进程中运行的SA的saId.xml文件内容。(比如AbilityManagerService,WindowManagerService,PowerManagerService等SA的配置文件都会被集成到foundation.xml中)。

  • Cfg配置文件

  cfg配置文件为linux提供的native进程拉起策略,开机启动阶段由init进程解析cfg文件把目标进程拉起(动态加载的除外)。foundation进程的配置文件在systemabilitymgr子系统中。

 foundation\systemabilitymgr\safwk\etc\profile\foundation.cfg
 34     "services" : [{
 35             "name" : "foundation",
 36             "path" : ["/system/bin/sa_main", "/system/profile/foundation.json"],
 37             "importance" : -20,
 38             "uid" : "foundation",
 39             "permission" : [
 40                 "ohos.permission.INPUT_MONITORING",
 41                 "ohos.permission.PERMISSION_USED_STATS",
 42                 "ohos.permission.DISTRIBUTED_SOFTBUS_CENTER",
 43                 "ohos.permission.DISTRIBUTED_DATASYNC",
 44                 "ohos.permission.MICROPHONE",
 45                 "ohos.permission.WRITE_CALL_LOG",
 46                 "ohos.permission.READ_CONTACTS",
 47                 "ohos.permission.READ_DFX_SYSEVENT",
 48                 "ohos.permission.GRANT_SENSITIVE_PERMISSIONS",
 49                 "ohos.permission.REVOKE_SENSITIVE_PERMISSIONS",
 50                 "ohos.permission.MANAGE_SECURE_SETTINGS",
 51                 "ohos.permission.GET_BUNDLE_INFO_PRIVILEGED",
 52                 "ohos.permission.START_ABILITIES_FROM_BACKGROUND",
 53                 "ohos.permission.ACCESS_SERVICE_DM",
 54                 "ohos.permission.STORAGE_MANAGER",
 55                 "ohos.permission.PROXY_AUTHORIZATION_URI",
 56                 "ohos.permission.ABILITY_BACKGROUND_COMMUNICATION",
 57                 "ohos.permission.USE_USER_IDM",
 58                 "ohos.permission.MANAGE_LOCAL_ACCOUNTS",
 59                 "ohos.permission.LISTEN_BUNDLE_CHANGE",
 60                 "ohos.permission.GET_TELEPHONY_STATE",
 61                 "ohos.permission.SEND_MESSAGES",
 62                 "ohos.permission.CONNECT_CELLULAR_CALL_SERVICE",
 63                 "ohos.permission.SET_TELEPHONY_STATE"

refer to

  • https://gitee.com/openharmony/communication_ipc
  • https://blog.csdn.net/procedurecode/article/details/130222081
  • https://gitee.com/openharmony/docs/blob/39467f023bec8cfca8ec2f97b99039b1dbd141e5/zh-cn/application-dev/ipc/ipc-rpc-overview.md
  • https://forums.openharmony.cn/forum.php?mod=viewthread&tid=2980
  • https://www.51cto.com/article/701821.html

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

0.机顶盒晶晨s905l3b芯片--刷入第三方系统+安卓9 root教程+armbian写入EMMC教程

机顶盒s905l3b芯片刷第三方系统安卓9 root教程刷armbian写入EMMC教程 声明&#xff1a; 由于固件、软件、镜像等持续更新&#xff0c;本文仅代表当前所使用版本的流畅安装记录。行文略长&#xff0c;关键代码处会配以截图展示&#xff0c;请自行对比是否存在差异导致安装失败…

视频监控平台:Liveweb视频汇聚融合平台智慧安防视频监控应用方案

Liveweb是一款功能强大、灵活部署的安防视频监控平台&#xff0c;支持多种主流标准协议&#xff0c;包括GB28181、RTSP/Onvif、RTMP等&#xff0c;同时兼容海康Ehome、海大宇等厂家的私有协议和SDK接入。该平台不仅提供传统安防监控功能&#xff0c;还支持接入AI智能分析&#…

汇编语言学习

想要理解栈溢出的最基本原理&#xff0c;汇编和栈是必不可少的&#xff0c;不然想我之前学了也是白学&#xff0c;原理都不知道 一、准备 1.安装gcc sudo apt-get build-dep gcc 这里显示版本不对&#xff0c;我用的是国内镜像源&#xff0c;需要换一下配置 sudo nano /e…

“乡村探索者”:村旅游网站的移动应用开发

3.1 可行性分析 从三个不同的角度来分析&#xff0c;确保开发成功的前提是有可行性分析&#xff0c;只有进行提前分析&#xff0c;符合程序开发流程才不至于开发过程的中断。 3.1.1 技术可行性 在技术实现层次&#xff0c;分析了好几种技术实现方法&#xff0c;并且都有对应的成…

Python + 深度学习从 0 到 1(02 / 99)

希望对你有帮助呀&#xff01;&#xff01;&#x1f49c;&#x1f49c; 如有更好理解的思路&#xff0c;欢迎大家留言补充 ~ 一起加油叭 &#x1f4a6; 欢迎关注、订阅专栏 【深度学习从 0 到 1】谢谢你的支持&#xff01; ⭐ Keras 快速入门&#xff1a; 神经网络的基本数据结…

MySQL用户授权

什么是数据库 数据库概述&#xff1a;数据库是按照一定的数据结构将数据存储在存储器的集合常见数据库软件 软件名开源跨平台厂 商Oracle否是甲骨文MySQL是是甲骨文SQL Server否否微软DB2否是IBMMongoDB是是MongoDB Inc.Redis是是开源软件Memcached是是开源软件 DB (DataBas…

2025年我国网络安全发展形势展望

展望2025年&#xff0c;我国网络安全产业有望迎来新的快速增长阶段&#xff0c;零信任安全架构将在各行各业加快应用落地&#xff0c;数据安全技术攻关和应用进程加快&#xff0c;关键基础设施安全能力不断提升。同时&#xff0c;也应关注国家级网络对抗风险加剧、网络安全产业…

GitPuk安装配置指南

GitPuk是一款开源免费的代码管理工具&#xff0c;上篇文章已经介绍了Gitpuk的功能与优势&#xff0c;这篇文章将为大家讲解如何快速安装和配置GitPuk&#xff0c;助力你快速的启动GitPuk管理代码 1. 安装 支持 Windows、Mac、Linux、docker 等操作系统。 1.1 Windows安装 下载…

ArcGIS+MIKE21 洪水淹没分析、溃坝分析,洪水淹没动态效果

洪水淹没分析过程&#xff1a; 一、所需数据&#xff1a; 1.分析区域DEM数据 二、ArcGIS软件 1.提取分析区域DEM&#xff08;水库坝下区域&#xff09; 2.DEM栅格转点 3.计算转换后几何点的x和y坐标值&#xff08;精度20、小数位3&#xff09; 4.导出属性表&#xff0c;形式…

中伟视界:AI识别摄像头+AI预警平台在矿山皮带空载监测中的应用

在矿山开采和矿物处理过程中&#xff0c;皮带运输机扮演着举足轻重的角色。它们负责将矿石、煤炭等物料从一处运送到另一处&#xff0c;是矿山生产流程中不可或缺的一环。然而&#xff0c;皮带运输机在运行过程中也面临着一些挑战&#xff0c;其中之一便是皮带空载问题。皮带空…

探索多模态大语言模型(MLLMs)的推理能力

探索多模态大语言模型&#xff08;MLLMs&#xff09;的推理能力 Multimodal Large Language Models (MLLMs) flyfish 原文&#xff1a;Exploring the Reasoning Abilities of Multimodal Large Language Models (MLLMs): A Comprehensive Survey on Emerging Trends in Mult…

AIGC时代:如何快速搞定Spring Boot+Vue全栈开发

文章目录 一、Spring Boot基础二、Vue.js基础三、Spring Boot与Vue.js集成四、性能优化与最佳实践《快速搞定Spring BootVue全栈开发》内容简介作者简介目录前言/序言本书内容本书特点读者对象 随着人工智能生成内容&#xff08;AIGC&#xff09;技术的迅速发展&#xff0c;内容…

mongodb和Cassandra

mongodb的一致性问题&#xff1a; 15.MongoDB的一致性(读关注与写关注)_mongo w选项-CSDN博客 孤儿节点问题&#xff1a; 技术干货 | MongoDB 偶遇孤儿文档及处理方法-腾讯云开发者社区-腾讯云 分片集群MongoDB迁移前清除孤儿文档 由数据迁移至MongoDB导致的数据不一致问题…

nginx-rtmp服务器搭建

音视频服务器搭建 本文采用 nginx/1.18.0和nginx-rtmp-module模块源代码搭建RTMP流媒体服务器 流程 查看当前服务器的nginx版本下载nginx和nginx-rtmp-module源代码重新编译nginx&#xff0c;并进行相关配置&#xff08;nginx.conf、防火墙等&#xff09;客户端测试连接测试搭…

初始 ShellJS:一个 Node.js 命令行工具集合

一. 前言 Node.js 丰富的生态能赋予我们更强的能力&#xff0c;对于前端工程师来说&#xff0c;使用 Node.js 来编写复杂的 npm script 具有明显的 2 个优势&#xff1a;首先&#xff0c;编写简单的工具脚本对前端工程师来说额外的学习成本很低甚至可以忽略不计&#xff0c;其…

(echarts)数据地图散点类型根据条件设置不同的标记图片

(echarts)数据地图散点类型根据条件设置不同的标记图片 1.用在线工具将本地图片转化base64格式 data(){return { base64Img:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADQ...",} }在线转换地址&#xff1a;https://www.jyshare.com/front-end/59/ 2.symbol属…

Linux高级--2.4.5 靠协议头保证传输的 MAC/IP/TCP/UDP---协议帧格式

任何网络协议&#xff0c;都必须要用包头里面设置写特殊字段来标识自己&#xff0c;传输越复杂&#xff0c;越稳定&#xff0c;越高性能的协议&#xff0c;包头越复杂。我们理解这些包头中每个字段的作用要站在它们解决什么问题的角度来理解。因为没人愿意让包头那么复杂。 本…

网络下载ts流媒体

网络下载ts流媒体 查看下载排序合并 很多视频网站&#xff0c;尤其是微信小程序中的长视频无法获取到准确视频地址&#xff0c;只能抓取到.ts片段地址&#xff0c;下载后发现基本都是5~8秒时长。 例如&#xff1a; 我们需要将以上地址片段全部下载后排序后再合成新的长视频。 …

小程序租赁系统开发指南与实现策略

内容概要 在如今这个快节奏的时代&#xff0c;小程序租赁系统的开发正逐渐成为许多商家提升服务质量与效率的重要选择。在设计这样一个系统时&#xff0c;首先要明白它的核心目标&#xff1a;便捷、安全。用户希望在最短的时间内找到需要的物品&#xff0c;而商家则希望通过这…

机器人C++开源库The Robotics Library (RL)使用手册(一)

强大的、完整的C机器人开源库 1、是否可以免费商用&#xff1f;2、支持什么平台&#xff1f;3、下载地址4、开始&#xff01; 1、是否可以免费商用&#xff1f; Robotics Library&#xff08;RL&#xff09;是一个独立的C库&#xff0c;用于机器人运动学、运动规划和控制。它涵…