任何良好和简单的RPC库进程间调用?
我需要发送一个(可能是一个)简单的单向命令从客户端进程到服务器进程,内置C ++types的参数(所以序列化非常简单)。 C ++,Windows XP +。
我正在寻找一个不需要复杂的configuration,提供简单的界面,不需要几个小时的学习,并没有商业使用的限制。 简单的问题的解决scheme。
Boost.Interprocess对于这个简单的任务太低级,因为不提供RPC接口。 套接字也可能是一个矫枉过正,因为我不需要在机器之间进行通信。 关于DCOM,CORBA等也是如此。 命名pipe道? 从来没有使用过,WinAPI上的任何好的库? 的openmpi?
我不认为套接字真的是矫枉过正。 替代方法都有自己的问题,并且套接字比命名pipe道,共享内存等得到更好的支持,因为几乎每个人都在使用它们。 本地系统的套接字速度可能不是问题。
还有Apache Thrift:
http://incubator.apache.org/thrift/
作为编组机制,围绕Google的protobuf库有一些RPC实现:
https://github.com/google/protobuf/blob/master/docs/third_party.md#rpc-implementations
有XML-RPC:
http://xmlrpc-c.sourceforge.net/
如果你的消息非常简单,我可能会考虑使用UDP数据包,那么就没有连接要pipe理。
你可能喜欢ZeroMQ这样的东西。 也许不是一个完整的RPC,而是一个可以用来制作RPC的原始字节消息框架。 它简单,轻便,性能令人印象深刻。 你可以容易地在它上面实现一个RPC。 下面是一个直接来自手册的示例服务器:
// // Hello World server in C++ // Binds REP socket to tcp://*:5555 // Expects "Hello" from client, replies with "World" // #include <zmq.hpp> #include <unistd.h> #include <stdio.h> #include <string.h> int main () { // Prepare our context and socket zmq::context_t context (1); zmq::socket_t socket (context, ZMQ_REP); socket.bind ("tcp://*:5555"); while (true) { zmq::message_t request; // Wait for next request from client socket.recv (&request); printf ("Received Hello"); // Do some 'work' sleep (1); // Send reply back to client zmq::message_t reply (5); memcpy ((void *) reply.data (), "World", 5); socket.send (reply); } return 0; }
本示例使用tcp://*.5555,但如果使用以下方法,则使用更高效的IPC技术:
socket.bind("ipc://route.to.ipc");
甚至更快的线程间协议:
socket.bind("inproc://path.for.client.to.connect");
如果你只需要支持Windows,我会使用Windows内置的RPC,我已经写了两篇介绍性的文章:
http://www.codeproject.com/KB/IP/rpcintro1.aspx
http://www.codeproject.com/KB/IP/rpcintro2.aspx
如果您只需要本地进程间通信,则可以使用ncalrpc
协议。
Boost.MPI 。 简单,快速,可扩展。
#include <boost/mpi/environment.hpp> #include <boost/mpi/communicator.hpp> #include <iostream> #include <sstream> namespace mpi = boost::mpi; int main(int argc, char* argv[]) { mpi::environment env(argc, argv); mpi::communicator world; std::stringstream ss; ss << "Hello, I am process " << world.rank() << " of " << world.size() << "."; world.send(1, 0, ss.str()); }
你可能甚至不需要一个图书馆。 Windows有一个深入到其核心API(windows.h)中的IPC机制。 你基本上可以将一个Windows消息发布到不同进程主窗口的消息队列中。 Windows甚至定义了一个标准的消息:WM_COPYDATA。
- WM_COPYDATA MSDN文件
- MSDN 演示代码
- 更多演示代码如下StackOverflow 响应
发送过程基本上是这样的:
- FindWindow函数
- 发信息
接收过程(窗口):
- 在Vista和更高版本必须使用ChangeWindowsMessageEx修改其消息filter
- 覆盖它的WindowProc
- 为了处理传入的WM_COPYDATA
我知道我们远离易于使用。 但是当然你可以坚持到CORBA。 如ACE / TAO
如果您只在Windows上工作,并且确实需要C ++接口,请使用COM / DCOM。 它基于RPC(反过来基于DCE RPC)。
这是非常简单的使用 – 如果你花时间学习的基础知识。
- ATL: http : //msdn.microsoft.com/en-us/library/3ax346b7( VS.71) .aspx
- 接口定义语言: http : //msdn.microsoft.com/en-us/library/aa367091(VS.85).aspx
我被告知RPC与Raknet是很好,很简单。
另外,你可以看看msgpack-rpc
更新
虽然Thrift / Protobuf更灵活,但我认为,但是需要以特定格式编写一些代码。 例如,Protobuf需要一些.proto文件,这个文件可以通过包中的特定编译器进行编译,生成一些类。 在某些情况下,代码的其他部分可能会更困难。 msgpack-rpc要简单得多。 它不需要写一些额外的代码。 这里是例子:
#include <iostream> #include <msgpack/rpc/server.h> #include <msgpack/rpc/client.h> class Server: public msgpack::rpc::dispatcher { public: typedef msgpack::rpc::request request_; Server() {}; virtual ~Server() {}; void dispatch(request_ req) try { std::string method; req.method().convert(&method); if (method == "id") { id(req); } else if (method == "name") { name(req); } else if (method == "err") { msgpack::type::tuple<> params; req.params().convert(¶ms); err(req); } else { req.error(msgpack::rpc::NO_METHOD_ERROR); } } catch (msgpack::type_error& e) { req.error(msgpack::rpc::ARGUMENT_ERROR); return; } catch (std::exception& e) { req.error(std::string(e.what())); return; } void id(request_ req) { req.result(1); } void name(request_ req) { req.result(std::string("name")); } void err(request_ req) { req.error(std::string("always fail")); } }; int main() { // { run RPC server msgpack::rpc::server server; std::auto_ptr<msgpack::rpc::dispatcher> dispatcher(new Server); server.serve(dispatcher.get()); server.listen("0.0.0.0", 18811); server.start(1); // } msgpack::rpc::client c("127.0.0.1", 18811); int64_t id = c.call("id").get<int64_t>(); std::string name = c.call("name").get<std::string>(); std::cout << "ID: " << id << std::endl; std::cout << "name: " << name << std::endl; return 0; }
产量
ID: 1 name: name
更复杂的例子,你可以在这里findhttps://github.com/msgpack/msgpack-rpc/tree/master/cpp/test
我使用XmlRpc C ++ for Windows 在这里find
真的好用:)但是这只是一个客户端的唯一副作用!
还有Microsoft消息队列 ,当所有进程都在本地计算机上时,这是非常简单的。
进程间通信最简单的解决scheme是使用文件系统。 请求和响应可以写成临时文件。 您可以为请求和响应文件制定一个命名约定。
这不会给你最好的performance,但也许它会足够好。