有没有好的、简单的用于进程间调用的 RPC 库?

发布于 2024-10-26 05:39:00 字数 366 浏览 7 评论 0 原文

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

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

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

I need to send a (probably one) simple one-way command from client processes to server process with arguments of builtin C++ types (so serialization is pretty simple). C++, Windows XP+.

I'm looking for a library that doesn't require complicated configuration, provides simple interface, doesn't require hours to days of learning and doesn't have commercial usage restrictions. Simple solution for simple problem.

Boost.Interprocess is too low-level for this simple task because doesn't provide RPC interface. Sockets are probably an overkill too because I don't need to communicate between machines. The same about DCOM, CORBA et al. Named pipes? Never used them, any good library over WinAPI? OpenMPI?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(12

寒江雪… 2024-11-02 05:39:00

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

Apache Thrift:

http://incubator.apache.org/thrift/

有一些 RPC 实现围绕 Google 的 protobuf 库作为封送机制:

https:/ /github.com/google/protobuf/blob/master/docs/third_party.md#rpc-implementations

有 XML-RPC:

http://xmlrpc-c.sourceforge.net/

如果您的消息确实很简单,我可能会考虑使用 UDP 数据包,那么就无需管理连接。

I don't think sockets are really overkill. The alternatives all have their own problems and sockets are far better supported than named pipes, shared memory, etc., because almost everyone is using them. The speed of sockets on local system is probably not an issue.

There's Apache Thrift:

http://incubator.apache.org/thrift/

There are a few RPC implementations wrapped around Google's protobuf library as the marshaling mechanism:

https://github.com/google/protobuf/blob/master/docs/third_party.md#rpc-implementations

There's XML-RPC:

http://xmlrpc-c.sourceforge.net/

If your messages are really simple, I might consider using UDP packets, then there are no connections to manage.

剧终人散尽 2024-11-02 05:39:00

您可能会喜欢 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");

You might like ZeroMQ for something like this. Perhaps not as much a complete RPC, as a raw byte messaging framework you could use to make an RPC. It's simple, lightweight and with an impressive performance. You can easilly implement an RPC on top of it. Here's an example server straight from the manual:

//
//  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;
}

This example uses tcp://*.5555, but uses more efficient IPC techniques if you use:

socket.bind("ipc://route.to.ipc");

or even faster inter thread protocol:

socket.bind("inproc://path.for.client.to.connect");
魔法少女 2024-11-02 05:39:00

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

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

您可以使用 ncalrpc< /a> 协议,如果您只需要本地进程间通信。

If you only need to support Windows I'd use the Windows built-in RPC, I've written two introductory articles about this:

http://www.codeproject.com/KB/IP/rpcintro1.aspx
http://www.codeproject.com/KB/IP/rpcintro2.aspx

You could use the ncalrpc protocol if you only need local inter-process communication.

如梦初醒的夏天 2024-11-02 05:39:00

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());
}

Boost.MPI. Simple, fast, scalable.

#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());
}
猫九 2024-11-02 05:39:00

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

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

If you are working on windows only, and really need a C++ interface, use COM/DCOM. It is based on RPC (in turn based on DCE RPC).

It is extremely simple to use -- provided you take the time to learn the basics.

画中仙 2024-11-02 05:39:00

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


发送过程基本上是:

接收进程(窗口):

You probably don't even need a library. Windows has an IPC mechanism built deeply into its core APIs (windows.h). You can basically post a windows message into the message-queue of a different processes main window. Windows even defines a standard message to do just that: WM_COPYDATA.


The sending process basically does:

The receiving process (window):

-柠檬树下少年和吉他 2024-11-02 05:39:00

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

I know that we are far away from easy to use. But of course you can stick to CORBA. E.g. ACE/TAO

不寐倦长更 2024-11-02 05:39:00

我听说 RPC 与 Raknet 很好而且很简单。

I'm told RPC with Raknet is nice and simple.

就是爱搞怪 2024-11-02 05:39:00

另外,您可以查看 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

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

Also, you might look at msgpack-rpc

Update

While Thrift/Protobuf are more flexible, I think, but there are require to write some code in specific format. For example, Protobuf needs some .proto file, which can be compile with specific compiler from package, that genegate some classes. In some cases it might be more difficult that other parts of code.
msgpack-rpc is much simpler. It doesn't require write some extra code. Here is example:

#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;
}

Output

ID: 1
name: name

More complicated examples you can find here https://github.com/msgpack/msgpack-rpc/tree/master/cpp/test

空名 2024-11-02 05:39:00

我正在使用适用于 Windows 的 XmlRpc C++ 在这里找到

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

I'm using XmlRpc C++ for Windows found here

Really easy to use :) But the only side effect that this is only a client!

东京女 2024-11-02 05:39:00

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

There's also Microsoft Messaging Queueing, which is fairly straightforward to use when all processes are on the local machine.

陪你搞怪i 2024-11-02 05:39:00

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

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

The simplest solution for interprocess-communication is to use the filesystem. Requests and responses can be written as temp files. You can work out a naming convention for request and response files.

This will not give you the best performance, but maybe it will be good enough.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文