C++远程过程调用库建议

13

我正在寻找关于C++实现的RPC库的建议,适用于C++开发人员。

一些要求和限制:

  • 应该在linux/unix和win32系统上工作
  • 能够执行自由函数和类方法
  • 最好是用现代C++编写而不是90年代/Java风格的C++
  • 能够在网络和异构架构上运行
  • 不要太慢或低效
  • 最好提供TR1样式的std::function等接口

我的示例用法是在远程机器上调用自由函数foo。

---snip---
// foo translation unit
int foo(int i, int j)
{
   return i + j;
}
---snip---


---snip---
// client side main
int main()
{
   //register foo on client and server
   //setup necassary connections and states

   int result;

   if (RPCmechanism.invoke("foo",4,9,result))
      std::cout << "foo(4,9) = " result << std::endl;
   else
      std::cout << "failed to invoke foo(4,9)!" << std::endl;

   return 0;
}
---snip---

能够实现上述或类似功能的东西将是很棒的。

注意:我不对其他语言绑定感兴趣。请不要因为它有其他语言绑定而提供解决方案。我只对用C++编写、设计良好、高效且适用于HPC场景的RPC框架感兴趣。


可能是跨平台通用C++ RPC库的重复问题。 - gbjbaanb
8个回答

8

这是一系列相当苛刻的要求...

虽然不能全部满足(因为我不确定是否有这样的产品存在 - 我向您推荐来自 ZeroC 的 ICE。ICE 部分由 CORBA 名人 Michi Henning 开发(请问电信行业的朋友,这真的不是个脏词),如果 CORBA 迟些开始并且不是由委员会开发的话,它将看起来像什么。

他们的 C++ 映射与 CORBA 完全不同,它使用了 STL 类型,并且总体上感觉更加现代化

它未能通过自由函数和 std::function 测试,但考虑到找到符合完整列表的产品的不可能性,它对许多剩余项做得很好。

祝好运


CORBA IDL 到 C++ 的映射并不使用 STL,但是IDL到C++11语言映射现在完全使用STL,并使用了C++11的所有新特性。 - Johnny Willemsen

7
我也对可行的C++ RPC实现感兴趣。经过一些研究,我发现etch、thrift和protocol buffers是最有前途的解决方案,但它们都没有真正满足我的需求。我的搜索标准如下:
1. 多语言支持,必须包括C++和PHP(目前不太重要的是C#、Java、Python和Perl); 2. 服务器可以只在Linux上编译/运行(长期目标是Windows); 3. 客户端必须在Windows和Linux上运行(可能还包括Mac); 4. 开源且商业友好(即没有GPL); 5. 必须支持开箱即用的加密。
以下是候选项:
1. Apache Etch 优点: - C绑定基于APR; - 支持加密; - 在两个平台上运行。 缺点: - 开发缓慢; - 没有PHP绑定。
2. Apache Thrift 优点: - 小巧; - 多语言绑定。 缺点: - 目前不支持加密(至少对于C++绑定正在开发中); - 在Windows上需要Cygwin。
3. Protocol Buffers与内部开发的RPC解决方案 优点: - 小巧; - 多语言绑定。 缺点: - 没有内置的RPC。
目前,我正在评估使用APR为Protobuf开发RPC层的可能性。不过搜索还在继续...
编辑:我成功地通过使用Apache Qpid(C++版本)与protobuf进行序列化来解决了其中一些问题,尽管它目前缺少我需要的一些功能。

5

旧的技术包括DCE-RPC、CORBA,

或者Protocol BuffersThriftEtch等网络技术,

或者像SOAP、REST这样的Web技术。

你需要选择哪种取决于你想做什么。例如,对于本地网络的快速高效RPC,需要使用轻量级的二进制RPC,如Protocol Buffers,但对于异构Web服务的RPC,则需要使用更加冗长的SOAP。

谷歌在其所有内部RPC中都使用PB,因此是一个不错的选择。Facebook使用Thrift,因此它绝不是小玩家,而微软则喜欢SOAP。


3
Protobuffers是一种消息序列化格式,SOAP是COM的等效物,而REST则是与C++、tr1 std::functions等无关的Web2.0主义思想。 - Matthieu N.
Protobuf支持RPC服务:http://code.google.com/apis/protocolbuffers/docs/proto.html#services - SoapBox
它是否提供了像问题中讨论的那样的机制,还是需要进一步的工作来获得那种功能? - Matthieu N.

3

1
它应该在Linux/Unix和Win32上都能工作,Thrift在Win32上能工作吗? - Matthieu N.
请查看 http://wiki.apache.org/thrift/ThriftInstallationWin32 以获取与 Thrift 安装相关的内容。 - Pawel Zubrycki
2
尽管可以使用MinGW和cygwin进行win32编程,但传统上使用msvc进行win32编程,我没有看到任何提到msvc win32的地方。 - Matthieu N.

2

是GPL。对于某些应用程序可能会有问题。 - rustyx

2

2
我看了一下,C++ API似乎没有建议可以调用free或类方法的功能,更像是一个类似ProtoBuffers的库。例如,假设我有一个名为foo的函数,如int foo(int i, int j) { return i+j} - 如何将foo注册到服务器实体中,然后如何在客户端上使用参数4和9调用foo? - Matthieu N.

1

你可以使用protobuf自己实现一个,并添加所有你想要的功能。这并不太难,而且你可以从中获得许多好处。


1
这个问题需要一个库,我不想自己开发。 - Matthieu N.
Protobuf 支持一些类似 RPC 的功能。虽然可能需要额外的工作来使其以特定的方式运行。 - SoapBox

1
以下代码取自一个 TAO CORBA 客户端示例,显示连接到服务器需要 3 行代码,并且调用函数只需要 1 行代码。请注意,函数调用看起来像本地函数调用一样。这可以是自由函数或成员函数。
// Bring in the IOR
Object_var factory_object =  orb->string_to_object (argv[1]);

// Now downcast the object reference 
My_Factory_var factory = My_Factory::_narrow (factory_object.in ());

// Now get the full name and price of the other arguments:
Widget_var widget = factory->get_widget (argv[i]);

// Get its name, put it on a _var so it is automatically
// released!
String_var full_name = widget->full_name ();

// Now get the price
Double price = widget->price ();

cout << "The price of a widget in \""
  << full_name.in () << "\" is $"
  << price << endl;

服务器端代码稍微复杂些,不太好展示。但在 CORBA 中,对于大多数你所寻求的操作,你需要创建一个IDL接口,通过编译器运行它,然后在存根的适当位置填入应用程序逻辑。因此,你的主要代码如下所示:
// First initialize the ORB, that will remove some arguments...
ORB_var orb = ORB_init(argc, argv, "ORB" /* the ORB name, it can be anything! */);
Object_var poa_object = orb->resolve_initial_references("RootPOA");
PortableServer::POA_var poa = PortableServer::POA::_narrow(poa_object.in());
PortableServer::POAManager_var poa_manager = poa->the_POAManager();
poa_manager->activate();

// Create the servant
My_Factory_i my_factory_i;

// Activate it to obtain the object reference
My_Factory_var my_factory = my_factory_i._this();

// Put the object reference as an IOR string
String_var ior = orb->object_to_string (my_factory.in());
orb->run();

    // Now in your stub file generated by the idl compiler, 
    char * Widget_i::full_name (

  )
  ACE_THROW_SPEC ((
    ::CORBA::SystemException
  ))
{
  return "Some widget name";
}

::CORBA::Double Widget_i::price (

  )
  ACE_THROW_SPEC ((
    ::CORBA::SystemException
  ))
{
  return 1.25;
}

请查看这个维基百科,以获取更多参考和示例


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接