全网唯一基于共享内存的C++ RPC框架

首先声明:我不是标题党,我是在找遍全网,没有找到一个基于共享内存实现、开源且跨平台的C++ RPC框架之后,才着手开发的这个框架。

项目地址:https://github.com/winsoft666/veigar


1. Veigar

Veigar一词来源于英雄联盟里面的“邪恶小法师-维迦”。

Veigar是一个跨平台的远程过程调用(RPC)框架,目前支持Windows、Linux平台。

Veigar基于共享内存技术实现,只支持本机进程或线程间的远程过程调用,这是Veigar与其他RPC框架(如Thrift、grpc)的最大不同之处。

2. 优势

与其他RPC框架相比,Veigar的优势在于:

  • 可以将任何函数暴露给调用方(不限语言,只要实现msgpack-rpc即可)。

  • 任何语言编写的程序都可以调用被暴露的函数。

  • 不需要学习IDL语言。

  • 不需要添加额外的代码生成步骤,仅需要C++代码。

  • 没有服务端和客户端的概念,每个Veigar实例间都可以相互调用。

  • 没有网络问题,如端口占用、半关闭状态等。

  • 没有诡异的端口假可用性问题(特别是在Windows系统上)。

3. 编译

虽然Veigar的底层是基于msgpack实现的,但已经将其包含到项目中,不需要额外编译和安装msgpack

虽然在veigar公共头文件引用了msgpack头文件,但这不会污染您的全局msgpack命名空间,因为Veigar中的msgpack命令空间为veigar_msgpack

Veigar仅支持编译为静态库。

可以使用CMake进行编译构建,也可以使用vcpkg进行安装,如:

vcpkg install veigar

4. 快速上手

在使用Veigar时,仅需要在项目中包含include目录,并链接静态库即可。

4.1 同步调用

下面是一个同步调用的示例:

本示例为了使代码更加简洁,没有对函数返回值进行校验,请在实际使用中不要这样做!

#include <iostream>
#include "veigar/veigar.h"int main(int argc, char** argv) {if (argc != 3) {return 1;}std::string channelName = argv[1];std::string targetChannelName = argv[2];veigar::Veigar vg;vg.bind("echo", [](const std::string& msg, int i, double d, std::vector<uint8_t> buf) {std::string result;// ...return result;});vg.init(channelName);std::vector<uint8_t> buf;veigar::CallResult ret = vg.syncCall(targetChannelName, 100, "echo", "hello", 12, 3.14, buf);if (ret.isSuccess()) {std::cout << ret.obj.get().as<std::string>() << std::endl;}else {std::cout << ret.errorMessage << std::endl;}vg.uninit();return 0;
}

每个Veigar实例有一个在本机范围内唯一的通道名称(Channel),在调用init函数时需要为Veigar指定通道名称,Veigar不会检测通道的唯一性,需要由调用者来保证通道名称的唯一性。

在上述示例中,需要通过命令行参数指定当前实例的通道名称和目标实例的通道名称,如:

sample.exe myself other

每个实例都绑定了名为echo的函数,该函数简单的原样返回msg参数字符串。

通过为syncCall函数指定“目标通道名称”、“函数名称”、“函数参数”及“超时毫秒数”就可以同步调用目标函数并得到调用结果。

4.2 拒绝异常

我不喜欢异常,因此Veigar也不会通过异常的形式来抛出错误,Veigar会主动捕获所有C++标准库、msgpack、boost异常,以返回值的形式返回给调用者。当调用失败时(!ret.isSuccess()),errorMessage中存储的错误信息就可能是Veigar捕获的异常信息。

4.3 异步调用

使用asyncCall函数可以实现异步调用。

下面是异步调用示例:

//
// 与同步调用相同
// ...
std::vector<uint8_t> buf;
std::shared_ptr<veigar::AsyncCallResult> acr = vg.asyncCall(targetChannelName, "echo", "hello", 12, 3.14, buf);
if (acr->second.valid()) {auto waitResult = acr->second.wait_for(std::chrono::milliseconds(100));if (waitResult == std::future_status::timeout) {// timeout}else {veigar::CallResult ret = std::move(acr->second.get());if(ret.isSuccess()) {std::cout << ret.obj.get().as<std::string>() << std::endl;}else {std::cout << ret.errorMessage << std::endl;}}
}vg.releaseCall(acr->first);//
// 与同步调用相同
// ...

与同步调用不同,asyncCall函数返回的是std::shared_ptr<veigar::AsyncCallResult>,而且调用者在获取到CallResult或不再关系调用结果时,需要调用releaseCall函数释放资源。

5. 性能

使用examples\echo程序作为测试用例。

启动A、B、C三个Channel,每个Channel分别使用2个线程向彼此调用100万次,如下图所示:
请添加图片描述

Windows平台测试结果

测试机器CPU配置:

12th Gen Intel(R) Core(TM) i7-12700H   2.30 GHz

测试结果如下:

Target channel names (Split by comma):
A,B,C
Async method(0/1):
0
Thread number for each target:
2
Call times each of thread:
1000000
Read/Write Timeout(ms):
100
[Thread 1, Target A] Calling...
[Thread 0, Target C] Calling...
[Thread 0, Target A] Calling...
[Thread 1, Target B] Calling...
[Thread 0, Target B] Calling...
[Thread 1, Target C] Calling...
[Thread 1, Target B] Total 1000000, Success 1000000, Error 0, Used: 59092341us, Average: 59us/call, 16922call/s.[Thread 0, Target B] Total 1000000, Success 1000000, Error 0, Used: 59112785us, Average: 59us/call, 16916call/s.[Thread 1, Target A] Total 1000000, Success 1000000, Error 0, Used: 59111520us, Average: 59us/call, 16917call/s.[Thread 0, Target C] Total 1000000, Success 1000000, Error 0, Used: 59126879us, Average: 59us/call, 16912call/s.[Thread 0, Target A] Total 1000000, Success 1000000, Error 0, Used: 59206766us, Average: 59us/call, 16889call/s.[Thread 1, Target C] Total 1000000, Success 1000000, Error 0, Used: 59299407us, Average: 59us/call, 16863call/s.

平均每次调用花费59微妙,每秒可以调用约16900次。

请添加图片描述

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

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

相关文章

2024年湖北省事业单位考试报名流程图解

⏰ 时间安排 ✔️ 注册&#xff1a;2024年2月19日至2月27日15:00 ✔️ 报名&#xff1a;2024年2月21日9:00至2月27日17:00 ✔️ 资格审查&#xff1a;2024年2月21日9:00至2月28日9:00 ✔️ 缴费确认&#xff1a;2024年2月28日9:00至3月1日24:00 ✔️ 岗位调整和改报&#…

上门服务系统|上门服务小程序|上门服务软件开发

随着移动互联网技术的普及&#xff0c;上门服务小程序系统成为现代企业数字化转型的关键一环。这一系统为消费者提供了更加便捷、高效以及个性化的服务体验&#xff0c;同时也为企业带来了更广阔的商业机会。让我们来看看上门服务小程序系统的优势和功能。 首先&#xff0c;上门…

vue3新特性-defineOptions和defineModel

defineOptions 背景说明&#xff1a; 有 <script setup> 之前&#xff0c;如果要定义 props, emits 可以轻而易举地添加一个与 setup 平级的属性。 但是用了 <script setup> 后&#xff0c;就没法这么干了 setup 属性已经没有了&#xff0c;自然无法添加与其平…

Docker基础篇(二)

docker run -d docker run -d 容器名或容器ID docker run -d 后台生成容器&#xff0c;并退出容器&#xff08;除容器中在运行脚本&#xff09; docker run -it 交互生成容器 docker run -d centos /bin/sh -c “while true; do echo zen; sleep 2;done” 查看容器中的进程…

【进程创建】

目录 进程创建的方式查看进程pid 调用系统调用创建子进程fock函数做了的工作子进程刚开始创建的状态 一个变量&#xff0c;两个不同的值创建子进程的作用 进程创建的方式 1.在操作系统上输入的指令。 2.已经启动的软件。 3.程序员在代码层面上调用系统调用创建进程。 linux中第…

服务器被黑该如何查找入侵痕迹以及如何防御攻击

当公司的网站服务器被黑&#xff0c;被入侵导致整个网站&#xff0c;以及业务系统瘫痪&#xff0c;给企业带来的损失无法估量&#xff0c;但是当发生服务器被攻击的情况&#xff0c;作为服务器的维护人员应当在第一时间做好安全响应&#xff0c;对服务器以及网站应以最快的时间…

【Java程序设计】【C00287】基于Springboot的疫情防控期间某村外出务工人员管理系统(有论文)

基于Springboot的疫情防控期间某村外出务工人员管理系统&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的疫情防控期间某村外出务工人员信息管理系统 本系统分为系统功能模块、管理员功能模块、用户功能模块、采集…

git 获取仓库代码与提交代码

1. 建文件夹&#xff0c;获取项目的完整代码 2.Git安装 打开安装程序后&#xff0c;一直点击下一步&#xff0c;直到以下位置&#xff1a; 此处代表使用VIM作为Git默认的编辑器。继续下一步&#xff0c;直到: 这里选择第一项&#xff0c;即仅仅在Bash中使用Git。如果有Linux的学…

ASCII编码的影响与作用:数字化时代的不可或缺之物

title: ASCII编码的影响与作用&#xff1a;数字化时代的不可或缺之物 date: 2024/2/25 16:03:37 updated: 2024/2/25 16:03:37 tags: ASCII起源标准化字符文本处理基础编程语言基石数据库存储标准跨平台兼容多语言编码基础 一、ASCII编码的起源 ASCII&#xff08;American St…

Qt的QFileSystemModel与QTreeView、QTableView、QListView的组合使用

1.相关描述 QFileSystemModel与QTreeView、QTableView、QListView的组合&#xff0c;当QTreeView点击发生改变&#xff0c;QTableView和QListView也会发生变化 2.相关界面 3.相关代码 mainwindow.cpp #include "mainwindow.h" #include "ui_mainwindow.h"…

2.WEB渗透测试-前置基础知识-web基础知识和操作系统

web基础知识 1.http协议 超文本传输协议是互联网上应用最广泛的一种网络协议。所有www文件都必须遵守的一个标准&#xff0c;是以 ASCII 码传输&#xff0c;建立在 TCP/IP 协议之上的应用层规范&#xff0c;通俗点说就是一种固定的通讯规则。 2、网络的三种架构及特点 网络应…

备战蓝桥杯————双指针技巧巧解数组3

利用双指针技巧来解决七道与数组相关的题目。 两数之和 II - 输入有序数组&#xff1a; 给定一个按升序排列的数组&#xff0c;找到两个数使它们的和等于目标值。可以使用双指针技巧&#xff0c;在数组两端设置左右指针&#xff0c;根据两数之和与目标值的大小关系移动指针。 …

年关将至送大礼 社区适时献爱心

在这个快节奏的时代&#xff0c;社区作为人们生活的重要组成部分&#xff0c;其凝聚力和互助精神显得尤为重要。2024年2月7日&#xff0c;实践队员李若钰有幸参与了社区礼盒分装的活动&#xff0c;这不仅仅是一次简单的劳动&#xff0c;更是一次心灵的洗礼和感悟。 礼盒分装&am…

Ansible user 模块 该模块主要是用来管理用户账号

目录 参数语法验证创建用户删除用户验证 删除用户 参数 comment  # 用户的描述信息 createhome  # 是否创建家目录 force  # 在使用stateabsent时, 行为与userdel –force一致. group  # 指定基本组 groups  # 指定附加组&#xff0c;如果指定为(groups)表示删除所有…

【深度学习目标检测】十九、基于深度学习的芒果计数分割系统-含数据集、GUI和源码(python,yolov8)

使用深度学习算法检测芒果具有显著的优势和应用价值。以下是几个主要原因&#xff1a; 特征学习的能力&#xff1a;深度学习&#xff0c;特别是卷积神经网络&#xff08;CNN&#xff09;&#xff0c;能够从大量的芒果图像中自动学习和提取特征。这些特征可能是传统方法难以手动…

JAVA算法和数据结构

一、Arrays类 1.1 Arrays基本使用 我们先认识一下Arrays是干什么用的&#xff0c;Arrays是操作数组的工具类&#xff0c;它可以很方便的对数组中的元素进行遍历、拷贝、排序等操作。 下面我们用代码来演示一下&#xff1a;遍历、拷贝、排序等操作。需要用到的方法如下 public…

gensim 实现 TF-IDF

目录 介绍 代码 介绍 TF-IDF&#xff08;Term Frequency-Inverse Document Frequency&#xff09; 含义&#xff1a; TF (Term Frequency): 词频&#xff0c;是指一个词语在当前文档中出现的次数。它衡量的是词语在文档内部的重要性&#xff0c;直观上讲&#xff0c;一个词…

用结构减法比较平面上4点结构的顺序

( A, B )---6*30*2---( 1, 0 )( 0, 1 ) 让网络的输入只有6个节点&#xff0c;AB训练集各由6张二值化的图片组成&#xff0c;A有4个点&#xff0c;B全是0.收敛误差7e-4&#xff0c;收敛199次&#xff0c;统计迭代次数平均值并排序。 如果行和列自由变换&#xff0c;迭代次数不…

区块链媒体:Web3.0突破7个爆款推广策略解析-华媒舍

Web3.0的概念代表着互联网的下一阶段发展&#xff0c;它将实现更加分散、安全、私密且能够实现无需中心化管理的网络生态系统。随着Web3.0的发展&#xff0c;推广策略也需要跟进并进行相应的创新。本文将为您介绍7个Web3.0时代的爆款推广策略&#xff0c;帮助你更好地了解和把握…

RM电控讲义【HAL库篇】(二)

8080并口模式是一种常见的计算机接口模式&#xff0c;主要用于LCD&#xff08;液晶显示屏&#xff09;模块。 在8080并口模式中&#xff0c;通信端口包括多种信号线&#xff0c;用于实现数据的读写和控制功能。主要的信号线包括&#xff1a; CS&#xff08;片选信号&#xff…