RCF(Remote Call Framework)是一个使用C++编写的RPC框架,在底层RCF支持多种传输实现方式(transport implementations). 包括TCP,UDP,多播,组播,win32命名管道和unix domain socket。下面我以一个例子讲述如何使用TCP完成一次RPC操做。php
须要注意的是,RCF官网上提供的是源码包,因此在使用时咱们要么本身将其编译为动态库,要么将整个源码加入咱们的项目中。html
使用RCF框架,咱们没必要像CORBA那样,须要使用IDL去定义接口。直接使用RCF提供的宏就能够定义。
如下代码定义了一个名为I_PrintService的接口,该接口包含了名为Print的函数,函数返回值为void,参数是const string &类型。java
值得注意的是RCF_METHOD_V1表示函数返回值为空且只有一个形参,相似的,RCF_METHOD_V2表示函数返回值为空且有两个参数,最多支持15个参数。那么若是咱们想要函数有返回值呢?好比一个返回值为int,有一个参数的函数。这时可使用RCF_METHOD_R1宏来声明该函数。严谨一点的表达以下所示,linux
RCF_METHOD_{V|R}{
}() ios
// Define the I_PrintService RCF interface. RCF_BEGIN(I_PrintService, "I_PrintService") RCF_METHOD_V1(void, Print, const std::string &) RCF_END(I_PrintService)
该代码的目的是在服务端实现一个Print函数,而后客户端使用本身的参数调用服务端的Print函数。c++
#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; }
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; }
编译时注意添加头文件的目录和-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框架
回调函数就是由调用方实现,可是由被调用函数(库函数)调用的函数。常见于c标准库和java,c++中的事件处理机制。回调函数可分为两种同步回调和异步回调。
dom
同步回调函数在调用方(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目录中
调用方调用库函数,并将本身实现的函数做为参数传递给库函数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; }
以上就是同步回调的实现。
异步回调在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);
https://www.ibm.com/developerworks/cn/linux/l-callback/
http://www.javashuo.com/article/p-zcdcjgyw-ck.html
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