56

我需要使用内置 C++ 类型的参数从客户端进程向服务器进程发送一个(可能是一个)简单的单向命令(因此序列化非常简单)。C++、Windows XP+。

我正在寻找一个不需要复杂配置、提供简单界面、不需要数小时到数天的学习时间并且没有商业使用限制的库。简单问题的简单解决方案。

Boost.Interprocess对于这个简单的任务来说太低级了,因为它不提供 RPC 接口。套接字也可能是一种过度杀伤,因为我不需要在机器之间进行通信。DCOM、CORBA 等人也是如此。命名管道?从来没有使用过它们,有什么好的 WinAPI 库吗?开放MPI?

4

12 回答 12

19

我不认为套接字真的是矫枉过正。替代方案都有自己的问题,并且套接字比命名管道、共享内存等得到更好的支持,因为几乎每个人都在使用它们。本地系统上的套接字速度可能不是问题。

有 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 数据包,那么就没有要管理的连接。

于 2011-03-23T00:20:42.667 回答
9

你可能会喜欢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");
于 2011-03-25T20:24:34.587 回答
6

如果你只需要支持 Windows 我会使用 Windows 内置的 RPC,我写了两篇关于这个的介绍性文章:

http://www.codeproject.com/KB/IP/r
​​pcintro1.aspx http://www.codeproject.com/KB/IP/r​​pcintro2.aspx

ncalrpc如果您只需要本地进程间通信,则可以使用该协议。

于 2011-03-29T19:41:59.180 回答
5

升压.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());
}
于 2011-03-31T20:29:52.237 回答
3

如果您只在 Windows 上工作,并且确实需要 C++ 接口,请使用 COM/DCOM。它基于 RPC(又基于 DCE RPC)。

它使用起来非常简单——只要您花时间学习基础知识。

于 2011-04-02T06:24:35.167 回答
2

你可能甚至不需要图书馆。Windows 在其核心 API (windows.h) 中内置了一个 IPC 机制。您基本上可以将 Windows 消息发布到不同进程主窗口的消息队列中。Windows 甚至定义了一个标准消息来做到这一点:WM_COPYDATA。


发送过程基本上是:

接收过程(窗口):

于 2011-03-30T11:34:29.873 回答
2

我知道我们离易于使用还很遥远。但当然你可以坚持使用 CORBA。例如ACE/TAO

于 2011-03-31T15:38:48.957 回答
1

我听说带有Raknet的 RPC 既好又简单。

于 2011-03-22T23:17:16.880 回答
1

另外,您可能会查看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(&params);
            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

您可以在这里找到更复杂的示例https://github.com/msgpack/msgpack-rpc/tree/master/cpp/test

于 2013-01-04T11:38:54.847 回答
0

我正在使用 XmlRpc C++ for Windows在这里找到

真的很容易使用:) 但是唯一的副作用就是这只是一个客户端!

于 2011-03-31T09:03:48.897 回答
0

还有Microsoft Messaging Queuing,当所有进程都在本地计算机上时,它使用起来相当简单。

于 2011-04-02T14:54:31.530 回答
-3

进程间通信最简单的解决方案是使用文件系统。请求和响应可以写为临时文件。您可以为请求和响应文件制定命名约定。

这不会给你最好的性能,但也许它会足够好。

于 2011-03-30T10:41:57.423 回答