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 <iostream>
#include <RCF/RCF.hpp>
// 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<I_PrintService>(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<I_PrintService> 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

参考

http://www.deltavsoft.com/doc/_init_deinit_8hpp.html#a450dd848bd45776c9a277ded406522c1

回调函数(callback)

1. 什么是回调函数

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


2. 同步回调

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

下面我们以一个c实例讲解什么是同步回调,以及使用回调函数的好处。

可以看到在server.c中,我们定义的库函数为callbk,该函数接受三个参数,前两个参数是函数指针fp的参数。

在头文件server.h中我们声明了一个接口funcp,该接口是一个接受两个int参数,返回值为int的函数指针。

库函数的实现

//   server.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "server.h" int callbk(int a, int b, funcp fp)
{
return fp(a, b);
} // server.h
#ifndef _SERVER_H
#define _SERVER_H
typedef 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;
}



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


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.ibm.com/developerworks/cn/linux/l-callback/

https://blog.csdn.net/morixinguan/article/details/65494239

http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=26000296&id=5782305

https://en.wikipedia.org/wiki/Callback_(computer_programming)

https://stackoverflow.com/questions/9596276/how-to-explain-callbacks-in-plain-english-how-are-they-different-from-calling-o/9652434#9652434

RCF的简单使用教程以及什么是回调函数的更多相关文章

  1. OpenMP的简单使用教程

    转自:http://binglispace.com/2015/01/09/openmp-intro/ OpenMP的简单使用教程 今天有幸参加了一个XSEDE OpenMP的workshop讲座,真是 ...

  2. 程序员,一起玩转GitHub版本控制,超简单入门教程 干货2

    本GitHub教程旨在能够帮助大家快速入门学习使用GitHub,进行版本控制.帮助大家摆脱命令行工具,简单快速的使用GitHub. 做全栈攻城狮-写代码也要读书,爱全栈,更爱生活. 更多原创教程请关注 ...

  3. knockout简单实用教程3

    在之前的文章里面介绍了一些KO的基本用法.包括基本的绑定方式,基本的ko的绑定语法包括text绑定,html绑定等等(如有不明请参照上两篇文章),下面呢介绍一下关于ko的其他方面的知识.包括比较特殊绑 ...

  4. GitHub这么火,程序员你不学学吗? 超简单入门教程 【转载】

    本GitHub教程旨在能够帮助大家快速入门学习使用GitHub. 本文章由做全栈攻城狮-写代码也要读书,爱全栈,更爱生活.原创.如有转载,请注明出处. GitHub是什么? GitHub首先是个分布式 ...

  5. sea.js简单使用教程

    sea.js简单使用教程 下载sea.js, 并引入 官网: http://seajs.org/ github : https://github.com/seajs/seajs 将sea.js导入项目 ...

  6. vim简单使用教程【转】

    vim的学习曲线相当的大(参看各种文本编辑器的学习曲线),所以,如果你一开始看到的是一大堆VIM的命令分类,你一定会对这个编辑器失去兴趣的.下面的文章翻译自<Learn Vim Progress ...

  7. 简单脱壳教程笔记(2)---手脱UPX壳(1)

    本笔记是针对ximo早期发的脱壳基础视频教程,整理的笔记. ximo早期发的脱壳基础视频教程 下载地址如下: http://down.52pojie.cn/%E5%90%BE%E7%88%B1%E7% ...

  8. 【git】git简单使用教程

    git的简单使用教程: 1.安装git bash客户端 2.打开git bash,cd到需要存储代码的路径下, 执行:git clone -b deploy ssh://git@gitlab.xxxx ...

  9. Flyway 简单入门教程

    原文地址:Flyway 简单入门教程 博客地址:http://www.extlight.com 一.前言 Flyway 是一款开源的数据库版本管理工具,它更倾向于规约优于配置的方式.Flyway 可以 ...

随机推荐

  1. 如何在一台机器上运行2个Tomcat

    比如:有两个版本的tomcat,一个5.*,一个6.*,此时由于两个工程分别部署在两个 版本的tomcat下,需要同时启动两个tomcat,以下是方法: 1.特别要注意:不要设置CATALINA_HO ...

  2. #学习tips——写给自己的语录

    用编程证明自己的观点! "我以为我懂了?"-- 花1/3的时间去学去记,剩下的时间应用做记忆实战. 记录一个转变 2018.6.7 (英文字幕-->无字幕!)good job ...

  3. Anaconda 执行命令报ssl错误

  4. 创建第一个windows服务

    windows服务应用程序是一种长期运行在操作系统后台的程序,它对于服务器环境特别适合,它没有用户界面,不会产生任何可视输出,任何用户输出都回被写进windows事件日志. 计算机启动时,服务会自动开 ...

  5. Android错题集

    在Android学习的过程中,遇到过很多迷之问题,在这里记下以防以后忘记,也可以顺便帮助一下遇到了相同问题的朋友. 1.自定义控件文字大小错误: 在自定义控件中获取的getDimension值为px值 ...

  6. python wsgi PEP333 中文翻译

    PEP 333 中文翻译 首先说明一下,本人不是专门翻译的,英文水平也不敢拿来献丑.只是这是两年前用python的时候为了自己学习方便而翻译的,记录着笔记自己看看而已.最近翻出来看看觉得还是放出来吧. ...

  7. shell编程报错:“syntax error near unexpected token `”

    今天写了个shell脚本,在自己机器上运行正常,给同事,运行报错syntax error near unexpected token `,左看右看shell脚本没有问题,没有办法google搜索,发现 ...

  8. 如何解决 Linux 虚拟机磁盘设备名不一致的问题

    问题描述 在 Linux 虚拟机内,将附加的多块数据磁盘以设备名(/dev/sdxx)的方式创建文件系统,并将之写入 /etc/fstab 文件中实现启动自动挂载功能.但是在虚拟机重启之后,会随机出现 ...

  9. C++ 类对象的初始化顺序 ZZ

    C++构造函数调用顺序 1.     创建派生类的对象,基类的构造函数优先被调用(也优先于派生类里的成员类): 2.    如果类里面有成员类,成员类的构造函数优先被调用:(也优先于该类本身的构造函数 ...

  10. centos无法用password登录,只能用public key的解决办法

    如上图只能用public key登录,只是我在17年申请的阿里云免费体验半年的服务器上遇到的, 那么我们用阿里云后台的远程连接按钮进入服务器,进入后 就看/etc/ssh/sshd_config文件配 ...