【通信中间件】Fdbus HellWorld实例

news2024/12/26 11:01:05

Fdbus实例教程

Fdbus简介

Fdbus 全称 Fast Distributed Bus(高速分布式总线),提供IPC+RPC功能。适用于多种OS:

  • Linux
  • QNX
  • AnroidOS
  • Window

Fdbus本质是Socket,IPC基于Unix domain socket,RPC基于TCP。使用Google Protobuf进行序列化和反序列化。

利用它,可以实现同域间的IPC通信,比如应用和OS间。也可以实现跨域、跨设备间通信,比如不同设备间数据传输,比如host/gust间的数据传输。
在这里插入图片描述

Fdbus的一些特点

  • 支持多种通信模式,比如点对点、注册/发布、广播等等。
  • 支持服务动态发现,自带心跳检测、重连,上线通知、离线检测等功能。
  • 支持一定程度的安全策略配置,token、证书、访问鉴权等等。
  • 支持Log调试,可以通过调试工具抓取在Fdbus上传输的内容。

其作者jeremy_cz(膜拜大神)对于FDBus的介绍非常详细。本文就不介绍了。关于FDBUS的内容,可以阅读作者的《Fast Distributed Bus - FDBus:高速分布式总线以及中间件开发框架》

Fdbus实例教程

基于Fdbus在一台Linux上,写一个C/S通信的Hellworld(例子)。
PC OS:Ubutun 20.04

编译Fdbus
  • 编译protobuf
git clone https://github.com/protocolbuffers/protobuf.git
git submodule update --init --recursive
mkdir -p build
cd build
# 这里把/usr作为了安装目录 
cmake -DCMAKE_INSTALL_PREFIX=/usr -DBUILD_SHARED_LIBS=1 ../cmake
make -j4
make install
  • 编译fdbus

git clone https://gitee.com/jeremyczhen/fdbus.git
cd fdbus
mkdir -p build/install
cd build
cmake -DCMAKE_INSTALL_PREFIX=install -Dfdbus_LOG_TO_STDOUT ../cmake
make -j4

编译成功后,会在build目录下生成大概以下文件,其中name_server是FDBUS用来管理服务名的进程,一会跑test需要运行它(具体请查看Fdbus作者jeremy_cz的博客)。编译生成内容大概如下

CMakeCache.txt
CMakeFiles
cmake_install.cmake
cmake_uninstall.cmake
fdbclienttest
fdbservertest
fdbxclient
fdbxserver
host_server
libfdbus-clib.so
libfdbus.so
logsvc
logviewer
lsclt
lsdp
lsevt
lshost
lssvc
Makefile
name_server
ntfcenter
HellWorld

这里直接在fdbus/example中新建了HelloWorld目录,目录结构(主要为了方便,直接借用fdbus源码的cmake。使用其他方式也可以,只要引用fdbus的lib和头文件即可。)

HelloWorld
-- HelloClient.cpp
-- HelloServer.cpp
-- HelloWorld.pb.h
-- HelloWorld.pb.cc
-- HelloWorld.proto

其中HelloWorld.pb.cc和HelloWorld.pb.h,是通过HelloWorld.proto生成的。生成命令

protoc --proto_path=. --cpp_out=. HelloWorld.proto
  • HelloWorld.proto
syntax = "proto2";

message HelloWorld
{
    required string name = 1; 
}
  • HelloServer.cpp
#define FDB_LOG_TAG "HELLO_SERVER"
#include <fdbus/fdbus.h>
#include "HelloWorld.pb.h"
#include <fdbus/CFdbProtoMsgBuilder.h>
#include <fdbus/cJSON/cJSON.h>
#include <fdbus/CFdbCJsonMsgBuilder.h>

using namespace ipc::fdbus;
// FDBUS提供的功能线程
static CBaseWorker main_worker;

static const int METHOD_ID = 1;

class HelloServer : public CBaseServer
{
public:
    HelloServer(const char*name, CBaseWorker* work = 0)
            : CBaseServer(name, work)
    {
            // Empty
    }


protected:
    void onOnline(const CFdbOnlineInfo &info)
    {
        std::cout << "connected to the client" << std::endl;
    }

    void onOffline(const CFdbOnlineInfo &info)
    {
        std::cout << "disconnected from client" << std::endl;
    }

    /* called when client calls invoke() */
    void onInvoke(CBaseJob::Ptr &msg_ref)
    {
        auto msg = castToMessage<CBaseMessage *>(msg_ref);
        static int32_t elapse_time = 0;
        switch (msg->code())
        {
            case METHOD_ID:
                {
                HelloWorld client;
                CFdbProtoMsgParser parser(client);
                if (!msg->deserialize(parser))
                {
                    return;
                }

                std::cout << "Client name " << client.name() << std::endl;
                /* fill in protocol buffer and reply to client */
                HelloWorld server;
                server.set_name("Linduo");
                CFdbProtoMsgBuilder builder(server);
                msg->reply(msg_ref, builder);
                }
                break;
            default:
                break;
        }
    }
};


int main(int argc, char*argv[])
{
/* start fdbus context thread */
    FDB_CONTEXT->start();
    fdbLogAppendLineEnd(true);
    FDB_CONTEXT->registerNsWatchdogListener([](const tNsWatchdogList &dropped_list)
    {
        for (auto it = dropped_list.begin(); it != dropped_list.end(); ++it)
        {
                printf("Error!!! Endpoint drops - name: %s, pid: %d\n",
                        it->mClientName.c_str(), it->mPid);
        }
    });

    CBaseWorker *worker_ptr = &main_worker;
    /* start worker thread */
    worker_ptr->start();

    /* create servers and bind the address: svc://service_name */
    for (int i = 1; i < argc; ++i)
    {
        std::string server_name = argv[i];
        std::string url(FDB_URL_SVC);
        url += server_name;
        server_name += "_server";
        auto server = new HelloServer(server_name.c_str(), worker_ptr);
        server->enableWatchdog(true);
        server->enableUDP(true);
        server->setExportableLevel(FDB_EXPORTABLE_SITE);
        server->bind(url.c_str());
    }

    // 将主线程变为WorkThread
    CBaseWorker background_worker;
    background_worker.start(FDB_WORKER_EXE_IN_PLACE);
}
  • HelloClient.cpp
#define FDB_LOG_TAG "HELLO_SERVER"
#include <fdbus/fdbus.h>
#include "HelloWorld.pb.h"
#include <fdbus/CFdbProtoMsgBuilder.h>
#include <fdbus/cJSON/cJSON.h>
#include <fdbus/CFdbCJsonMsgBuilder.h>

using namespace ipc::fdbus;
// FDBUS提供的功能线程
static CBaseWorker main_worker;

static const int METHOD_ID = 1;

class HelloServer : public CBaseServer
{
public:
    HelloServer(const char*name, CBaseWorker* work = 0)
            : CBaseServer(name, work)
    {
        // Empty
    }


protected:
    void onOnline(const CFdbOnlineInfo &info)
    {
        std::cout << "connected to the client" << std::endl;
    }

    void onOffline(const CFdbOnlineInfo &info)
    {
        std::cout << "disconnected from client" << std::endl;
    }

    /* called when client calls invoke() */
    void onInvoke(CBaseJob::Ptr &msg_ref)
    {
        auto msg = castToMessage<CBaseMessage *>(msg_ref);
        static int32_t elapse_time = 0;
        switch (msg->code())
        {
            case METHOD_ID:
            {
                HelloWorld client;
                CFdbProtoMsgParser parser(client);
                if (!msg->deserialize(parser))
                {
                    return;
                }

                std::cout << "Client name " << client.name() << std::endl;
                /* fill in protocol buffer and reply to client */
                HelloWorld server;
                server.set_name("Linduo");
                CFdbProtoMsgBuilder builder(server);
                msg->reply(msg_ref, builder);
            }
                break;
            default:
                break;
        }
    }
};


int main(int argc, char*argv[])
{
    /* start fdbus context thread */
    FDB_CONTEXT->start();
    fdbLogAppendLineEnd(true);
    FDB_CONTEXT->registerNsWatchdogListener([](const tNsWatchdogList &dropped_list)
    {
        for (auto it = dropped_list.begin(); it != dropped_list.end(); ++it)
        {
                printf("Error!!! Endpoint drops - name: %s, pid: %d\n",
                        it->mClientName.c_str(), it->mPid);
        }
    });

    CBaseWorker *worker_ptr = &main_worker;
    /* start worker thread */
    worker_ptr->start();

    /* create servers and bind the address: svc://service_name */
    for (int i = 1; i < argc; ++i)
    {
        std::string server_name = argv[i];
        std::string url(FDB_URL_SVC);
        url += server_name;
        server_name += "_server";
        auto server = new HelloServer(server_name.c_str(), worker_ptr);
        server->enableWatchdog(true);
        server->enableUDP(true);
        server->setExportableLevel(FDB_EXPORTABLE_SITE);
        server->bind(url.c_str());
    }

    // 将主线程变为WorkThread
    CBaseWorker background_worker;
    background_worker.start(FDB_WORKER_EXE_IN_PLACE);
}
  • 编译部分:加到了dbus/cmake/pb-example/example.cmake中,在cmake中编译上面的cpp
add_executable(helloworldclient
    ${PACKAGE_SOURCE_ROOT}/example/HelloWorld/HelloClient.cpp
    ${PACKAGE_SOURCE_ROOT}/example/HelloWorld/HelloWorld.pb.cc
    ${PACKAGE_SOURCE_ROOT}/example/HelloWorld/HelloWorld.pb.h
)

add_executable(helloworldserver
    ${PACKAGE_SOURCE_ROOT}/example/HelloWorld/HelloServer.cpp
    ${PACKAGE_SOURCE_ROOT}/example/HelloWorld/HelloWorld.pb.cc
    ${PACKAGE_SOURCE_ROOT}/example/HelloWorld/HelloWorld.pb.h
)
  • 在fdbus/cmake/CMakeLists.txt中引入了这个cmake,并且加入了C++14的Flag。
if (MSVC)
    add_definitions("-D__WIN32__")
elseif(fdbus_ANDROID)
    add_definitions("-D__LINUX__")
else()
    if(CMAKE_COMPILER_IS_GNUCXX)
        set(CMAKE_CXX_FLAGS "-std=gnu++14 -Wall -Wl,--copy-dt-needed-entries ${CMAKE_CXX_FLAGS}")
    endif()
    #add_compile_options(-g -O0)
    add_definitions("-D__LINUX__")
endif()


include(pb-example/example.cmake)
  • 重新运行cmake,然后make。编译出helloworldclient和helloworldserver两个文件。
cmake -DCMAKE_INSTALL_PREFIX=install -Dfdbus_LOG_TO_STDOUT ../cmake
make -j4
运行HelloWorld
  • 开三个终端,分别运行,无先后顺序。Server/Client运行无需先后顺序,这点也是Fdbus的有点。大概原理是,通过服务动态绑定,当网络中的Server上线时,Client会自动连接该Service。
# 开3个终端,分别运行。其中name_server(用来实现服务动态绑定)
./name_server
./helloworldserver my
./helloworldclient my

执行成功后:
helloworldserver会输出从客户端收到的内容。

connected to the client
Client name Adver

helloworldclient会输出从服务端收到的内容。

connected to the server
Server name Linduo

PS:name_server在服务端和客户端连接时,不是必须得。如果两端指定了IPC端口,可以不使用name_server连接。但是不使用name_server时,就需要控制好连接时序。所以一般来讲,应用时都是启动一个name_server。

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

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

相关文章

Elasticsearch 索引 blocks:深入探讨数据保护

Elasticsearch 作为搜索和分析数据的首选分布式引擎在技术领域脱颖而出&#xff0c;尤其是在处理日志、事件和综合文本搜索时。 它的与众不同之处在于它如何让你使用各种块选项调整对其索引的访问。 这对于那些负责技术项目的人&#xff08;比如管理员和编码员&#xff09;来说…

AI手机,走入小径分岔的花园

博尔赫斯在他的成名作《小径分岔的花园》里&#xff0c;描述了一种奇妙的世界观&#xff1a;一个可能性被选择之后&#xff0c;出现了许多不同的后世&#xff0c;许多不同的时间。 在现实世界中&#xff0c;选择不会如此神奇。但站在岔路口的抉择&#xff0c;也一定会带来结果的…

【Week-Y7】使用自己的数据集训练YOLO-v8

文章目录 一、官方环境配置与测试1. 配置环境2. 用官方图片测试&#xff08;图片下载失败&#xff09;3. 用本地图片测试&#xff0c;检查配置的环境是否可用 二、使用自己的数据集进行训练测试1. 执行split_train_val.py文件2. 执行python .\voc_label.py文件3. 创建fruit.yam…

本地搭建llama大模型及对话UI

环境说明&#xff1a;MBP 2023 M2Pro芯片 用到的工具/组件/技术&#xff1a;ollama、llama3:8b、docker、open-webui 1.下载ollama ollama官网下载地址&#xff1a;https://ollama.com/download 到ollama官网地址下载对应操作系统版本的ollama平台&#xff0c;按照安装指引…

python报错SyntaxError

如果报这个错&#xff0c; 在你的相应的demo.py文件首行输入下面的&#xff0c;可以多试一下&#xff0c;之后就好了。 这个解决方法也是参考其他大佬的做法&#xff0c;不知道为什么python中#是注释&#xff0c;这个也会起作用。 然后就神奇的发现问题解决了。发现下面的代码…

天地图路径规划功能实现

目录 1、天地图路径规划2、路径规划3、参数说明4、Demo 1、天地图路径规划 天地图Web服务API为用户提供HTTP/HTTPS接口&#xff0c;即开发者可以通过这些接口使用各类型的地理信息数据服务&#xff0c;可以基于此开发跨平台的地理信息应用。 Web服务API对所有用户开放。使用本…

Tensorflow2.0笔记 - ResNet实践

本笔记记录使用ResNet18网络结构&#xff0c;进行CIFAR100数据集的训练和验证。由于参数较多&#xff0c;训练时间会比较长&#xff0c;因此只跑了10个epoch&#xff0c;准确率还没有提升上去。 import os import time import tensorflow as tf from tensorflow import keras …

自动安装环境shell脚本使用和运维基础使用讲解

title: 自动安装环境shell脚本使用和运维基础使用讲解 tags: [shell,linux,运维] categories: [开发记录,系统运维] date: 2024-3-27 14:10:15 description: 准备和说明 确认有网。 依赖程序集&#xff0c;官网只提供32位压缩包&#xff0c;手动编译安装后&#xff0c;在64位机…

动态数据结构中的表扩张性:摊还分析、伪代码与C语言实现

动态数据结构中的表扩张性&#xff1a;摊还分析、伪代码与C语言实现 引言表扩张性的概念摊还分析在表扩张性中的应用伪代码示例&#xff1a;TABLE-INSERT操作C语言实现结论 引言 在处理数据结构时&#xff0c;尤其是表&#xff08;或数组&#xff09;&#xff0c;我们经常面临…

STM32标准库编译前置条件配置

本文基于stm32f104系列芯片&#xff0c;记录编程代码前需要的操作&#xff1a; 添加库文件 在ST官网下载标准库STM32F10x_StdPeriph_Lib_V3.5.0&#xff0c;解压后&#xff0c;得到以下界面 启动文件 进入Libraries&#xff0c;然后进入CMSIS&#xff0c;再进入CM3&#xff…

CUDA内存模型

核函数性能并不只与线程束的执行有关。 CUDA内存模型概述 GPU和CPU内存模型的主要区别是&#xff0c;CUDA编程模型能将内存层次结构更好地呈现给用户&#xff0c;能让我们显示的控制它的行为。 对程序员来说&#xff0c;一般有两种类型的存储器&#xff1a; 可编程的&#x…

【Qt QML】用CMake管理Qt工程

CMake是一个开源、跨平台的工具系列&#xff0c;用于构建、测试和打包软件。CMake使用简单的独立配置文件来控制软件编译过程。与许多跨平台系统不同&#xff0c;CMake被设计为与本地构建环境结合使用。 下面我们在CMake项目中使用Qt的最基本方法。首先&#xff0c;创建一个基本…

向量体系结构:向量执行时间

看《计算机体系结构 量化研究方法》做的笔记&#xff0c;接着上一篇写 计算机体系结构&#xff1a;向量体系结构介绍-CSDN博客 向量处理器工作的示例 SAXPY或DAXPY循环。 aXY SAXPY代表“单精度aX加Y”&#xff0c;进行单精度浮点数的运算&#xff0c;其中a是一个标量&#x…

测试开发工具开发 -JMeter 函数二次开发

在JMeter中开发自定义函数是一个常见的需求&#xff0c;允许我们扩展JMeter的功能以适应特定的测试需求。自定义函数可以用来处理数据&#xff0c;生成输出&#xff0c;或者执行特定的运算。通过JMeter函数二次开发可以帮我们解决实际测试过程中造数难的问题 用过JMeter的同学…

搭建vue3组件库(三): CSS架构之BEM

文章目录 1. 通过 JS 生成 BEM 规范名称1.1 初始化 hooks 目录1.2 创建 BEM 命名空间函数1.3 通过 SCSS 生成 BEM 规范样式 2. 测试 BEM 规范 BEM 是由 Yandex 团队提出的一种 CSS 命名方法论&#xff0c;即 Block&#xff08;块&#xff09;、Element&#xff08;元素&#xf…

WORD排版常见问题与解决方案

前言 近期使用word软件进行论文排版工作&#xff0c;遇到了一些常见的问题&#xff0c;记录一下&#xff0c;避免遗忘。 基本配置 系统环境&#xff1a;win10/win11 word版本&#xff1a;Microsoft Office LTSC 专业增强版 2021 问题与解决方案 问题1&#xff1a;页眉显示内…

C——双向链表

一.链表的概念及结构 链表是一种物理存储单元上非连续、非顺序的存储结构&#xff0c;数据元素的逻辑顺序是通过链表中的指针链接次序实现的。什么意思呢&#xff1f;意思就是链表在物理结构上不一定是连续的&#xff0c;但在逻辑结构上一定是连续的。链表是由一个一个的节点连…

使用递归函数,将一串数字每位数相加求和

代码结果&#xff1a; #include<stdio.h> int DigitSum(unsigned int n) {if (n > 9)return DigitSum(n / 10) (n % 10);elsereturn n; } int main() {unsigned int n;scanf("%u", &n);int sum DigitSum(n);printf("%d\n", sum);return 0; …

持续更新|UNIAPP适配APP遇到的问题以及解决方案

在使用UNIAPP开发APP的时候遇到的一些奇奇怪怪问题记录 组件样式丢失 问题&#xff1a;组件引入界面中&#xff0c;在小程序和H5环境下样式正常&#xff0c;而在APP中却出现高度异常问题 解决&#xff1a;增加view标签将组件包裹起来即可正常显示 解决前&#xff1a; 解决后…

SCI一区 | MFO-CNN-LSTM-Mutilhead-Attention多变量时间序列预测(Matlab)

SCI一区 | MFO-CNN-LSTM-Mutilhead-Attention多变量时间序列预测&#xff08;Matlab&#xff09; 目录 SCI一区 | MFO-CNN-LSTM-Mutilhead-Attention多变量时间序列预测&#xff08;Matlab&#xff09;预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.Matlab实现MFO-CNN…