博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
RCF的简单使用教程以及什么是回调函数
阅读量:6885 次
发布时间:2019-06-27

本文共 4227 字,大约阅读时间需要 14 分钟。

RCF的使用教程

RCF(Remote Call Framework)是一个使用C++编写的RPC框架,在底层RCF支持多种传输实现方式(transport implementations). 包括TCP,UDP,多播,组播,win32命名管道和unix domain socket。下面我以一个例子讲述如何使用TCP完成一次RPC操作。

需要注意的是,RCF官网上提供的是源码包,所以在使用时我们要么自己将其编译为动态库,要么将整个源码加入我们的项目中。

1. 定义接口

使用RCF框架,我们不必像CORBA那样,需要使用IDL去定义接口。直接使用RCF提供的宏就可以定义。

以下代码定义了一个名为I_PrintService的接口,该接口包含了名为Print的函数,函数返回值为void,参数是const string &类型。

值得注意的是RCF_METHOD_V1表示函数返回值为空且只有一个形参,类似的,RCF_METHOD_V2表示函数返回值为空且有两个参数,最多支持15个参数。那么如果我们想要函数有返回值呢?比如一个返回值为int,有一个参数的函数。这时可以使用RCF_METHOD_R1宏来声明该函数。严谨一点的表达如下所示,

RCF_METHOD_{V|R}{}()

// Define the I_PrintService RCF interface.RCF_BEGIN(I_PrintService, "I_PrintService")    RCF_METHOD_V1(void, Print, const std::string &)RCF_END(I_PrintService)

2. 服务端的编写

该代码的目的是在服务端实现一个Print函数,然后客户端使用自己的参数调用服务端的Print函数。

  1. 创建一个初始化对象RcfInit init. RcfInit的默认构造函数会调用init(RcfConfigT *=nullptr)初始化RCF库的引用计数值。
  2. 实例化一个RCF server,参数是具体的传输方式,TCP,UDP,命名管道等等。
  3. 将服务器绑定到声明的接口
  4. 启动服务器
#include 
#include
// Define the I_PrintService RCF interface.RCF_BEGIN(I_PrintService, "I_PrintService") RCF_METHOD_V1(void, Print, const std::string &)RCF_END(I_PrintService)// Server implementation of the I_PrintService RCF interface.class PrintService{public: void Print(const std::string & s) { std::cout << "I_PrintService service: " << s << std::endl; }};int main(){ try { // Initialize RCF. 1. RCF::RcfInit rcfInit; // Instantiate a RCF server. 2. RCF::RcfServer server(RCF::TcpEndpoint("127.0.0.1", 50001)); // Bind the I_PrintService interface. 3. PrintService printService; server.bind
(printService); // Start the server. 4. server.start(); std::cout << "Press Enter to exit..." << std::endl; std::cin.get(); } catch ( const RCF::Exception & e ) { std::cout << "Error: " << e.getErrorMessage() << std::endl; } return 0;}

3. 客户端的编写

  1. 声明接口
  2. 创建一个初始化对象RcfInit init.
  3. 实例化一个RCF客户端
  4. 调用服务器的函数
RCF_BEGIN(I_PrintService, "I_PrintService")    RCF_METHOD_V1(void, Print, const std::string &)RCF_END(I_PrintService)int main(){    try    {        // Initialize RCF.        RCF::RcfInit rcfInit;        std::cout << "Calling the I_PrintService Print() method." << std::endl;                // Instantiate a RCF client.        RcfClient
client(RCF::TcpEndpoint("127.0.0.1", 50001)); // Connect to the server and call the Print() method. client.Print("message from dennis"); } catch ( const RCF::Exception & e ) { std::cout << "Error: " << e.getErrorMessage() << std::endl; } return 0;}

4. 编译运行

编译时注意添加头文件的目录和-luuid

g++ server.cpp ../src/RCF/RCF.cpp -lpthread -ldl -std=c++1y -luuid -I ../include/ -o server

695616-20180607111237254-513331643.png

参考

回调函数(callback)

1. 什么是回调函数

回调函数就是由调用方实现,但是由被调用函数(库函数)调用的函数。常见于c标准库和java,c++中的事件处理机制。回调函数可分为两种同步回调和异步回调。

695616-20180607111358605-1968948653.png


2. 同步回调

同步回调函数在调用方(caller)调用后立即执行

下面我们以一个c实例讲解什么是同步回调,以及使用回调函数的好处。
可以看到在server.c中,我们定义的库函数为callbk,该函数接受三个参数,前两个参数是函数指针fp的参数。
在头文件server.h中我们声明了一个接口funcp,该接口是一个接受两个int参数,返回值为int的函数指针。
---

库函数的实现

//   server.c#include 
#include
#include
#include "server.h"int callbk(int a, int b, funcp fp){ return fp(a, b);}// server.h#ifndef _SERVER_H#define _SERVER_Htypedef int (*funcp)(int, int); int callbk(int, int, funcp);#endif

我们可以将server.c制作成动态库并将其放置到/usr/lib目录中

> gcc -shared -fPIC server.c -o libserver.so

调用方的实现

调用方调用库函数,并将自己实现的函数作为参数传递给库函数callbk。

#include "server.h"int add_int(int a, int b){    return (a+b);}int main(){    int sum = callbk(1, 2, add_int);    printf("sum=%d\n", sum);    return 0;}

695616-20180607111226965-206197253.png

以上就是同步回调的实现。


3. 异步回调

异步回调在unix编程,窗口程序,以及需要事件处理机制的程序中被广泛使用。举几个例子,

1 pthread创建线程

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,                  void *(*start_routine) (void *), void *arg);

2 unix注册信号处理函数

以下代码为信号SIGUSR1注册了一个用户自定义的sig_usr函数

if ( signal(SIGUISR1, sig_usr)  == SIG_ERR)     perrror("sig err");

3 java swing

以下代码用户自定义了回调类MyListener

class MyListener implements ActionListener {    ...    public void actionPerformed(ActionEvent event)     {            //some operation    }}JButton yButton = new JButton();yButton.addActionListener(new MyListener);

4. reference

转载于:https://www.cnblogs.com/dennis-wong/p/9149636.html

你可能感兴趣的文章
mysql建表---级联删除
查看>>
分布式队列神器 Celery
查看>>
windows 允许其他电脑访问本地mysql数据库
查看>>
.Net进阶系列(21)-跨域请求
查看>>
标准输入的EOF
查看>>
如何使用Git命令将项目从github或者服务器上克隆下来
查看>>
cplusplus.com
查看>>
svg了解一下
查看>>
使用slidingmeu_actionbarsherlock_lib的问题和The hierarchy of the type MainActivity is inconsistent...
查看>>
VS2015新功能
查看>>
数组、ArrayList、List<T>区别和选择
查看>>
使用MVC Razor生成格式良好的HTML Body作为邮件内容
查看>>
扑克游戏 模拟赛C组
查看>>
JUnit4 中@AfterClass @BeforeClass @after @before的区别对比
查看>>
jquery中的ajax参数说明
查看>>
Sublime Text2的常用技巧总结(更新中...)
查看>>
99%的人都理解错了HTTP中GET与POST的区别
查看>>
springboot mvc beetl模板 自定义错误的后缀问题
查看>>
ext常用属性
查看>>
PL/SQL连接64位Oracle配置方法
查看>>