any good and simple RPC library for inter-process calls? [closed]
Asked Answered
A

12

59

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?

Alcoholism answered 22/3, 2011 at 22:33 Comment(2)
Windows has some RPC support baked in. You can use a named pipe among other things as the transport. I don't suggest it as an answer because "simple" it really isn't. htp//sn.cosftco/en-us/lirary/aa378651(v=VS.85).aspxBelanger
Oops msdn.microsoft.com/en-us/library/aa378651(v=VS.85).aspxBelanger
E
21

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.

Ehrenburg answered 23/3, 2011 at 0:20 Comment(6)
yeah, if I won't find anything simpler most probably I'll use Boost.Asio for this (I already use it for networking communication in this project)Alcoholism
btw, is it 100% guaranteed that UDP packet cannot be lost if sent to local process?Alcoholism
@Andy UDP packets do not have a delivery guarantee, so if you need to be 100% sure you design the protocol so the receiver replies and the sender keeps re-sending until it gets a response. If you're going to do that you should probably just use TCP. On the other hand, I'd be really surprised if UDP packets got lost within the local system, I think that only happens with network connection problems, or if you're sending many packets too fast and buffers fill up.Ehrenburg
@Andy There's also a size limit for UDP transmits, your messages have to fit in a single packet. If you're going to have to re-assemble your data, again you probably just want to go with TCP.Ehrenburg
@Tim Sylvester UDP packet loss isn't very rare even on a LAN. Your ethernet switch will easily drop packets, your network card will drop packets, your OS will drop packets. All it takes is that a few packets (any packet,not just your UDP packets) pass through the switch/network card/router a bit too fast, and some will get droppedFaydra
@Faydra If your LAN is actually being used near its capacity that's true. In any case, the question explicitly states that we're talking about communicating between two processes on the same host, not a LAN connection. In that situation I expect dropped packets to be very rare unless you're sending them faster than they can be processed.Ehrenburg
G
9

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");
Gauge answered 25/3, 2011 at 20:24 Comment(1)
and seems stuck half way from C to C++Alcoholism
G
6

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.

Gunther answered 29/3, 2011 at 19:41 Comment(6)
nice work, haven't you thought about developing a C++ library over MS RPC?Alcoholism
@Andy T: Yes, we use Windows RPC at work using an internal C++ wrapper library. But the problem with Windows RPC is just that, it is Windows only. We are currently working on expanding beyond just Windows to other platforms, and looking for other solutions.Gunther
MSRPC is derived from DCE/RPC which in the meantime has been released under a BSD license. The two can be made to work together, see msdn.microsoft.com/en-us/library/aa230583%28v=vs.60%29.aspxLiebman
@dalle, how is you success in search?Needle
@DzmitryLahoda: We have found several different alternatives. RPC over MessagePack, RPC over Protocol Buffers, JSON-RPC, Thrift, XML-RPC.Gunther
Thank you @dalle, I used your article to implement a pretty complete 64bit to 32big dll proxy and has been working perfectly for 2 years.Exponent
T
5

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());
}
Tridentine answered 31/3, 2011 at 20:29 Comment(1)
seems easy enough. As I know, Boost.MPI is just a wrapper over C-interface to a MPI-compatible library. OpenMPI seems the most popular one. Is it easy to setup and configure? Also this example doesn't look like RPC, does Boost.MPI has any RPC support to speed-up development? how difficult is IPC configuration?Alcoholism
M
3

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.

Mekong answered 2/4, 2011 at 6:24 Comment(0)
L
2

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):

Liebman answered 30/3, 2011 at 11:34 Comment(0)
G
2

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

Growth answered 31/3, 2011 at 15:38 Comment(0)
B
1

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

Burkett answered 22/3, 2011 at 23:17 Comment(1)
I used it in the past and tbh I don't like it. mostly because I had stability problems with raknet. other reasons deserve a separate post. what I need to acknowledge - raknet feature set and support is impressiveAlcoholism
K
1

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

Output

ID: 1
name: name

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

Kampala answered 4/1, 2013 at 11:38 Comment(2)
Whilst this may theoretically answer the question, it would be preferable to include the essential parts of the answer here, and provide the link for reference.Stepheniestephens
And the streaming feature looks very niceOwensby
U
0

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

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

Underwear answered 31/3, 2011 at 9:3 Comment(0)
N
0

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

Natatory answered 2/4, 2011 at 14:54 Comment(0)
N
-3

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.

Neutralize answered 30/3, 2011 at 10:41 Comment(2)
not sure it's simple, especially you need to think about a crashed application that left temp file on disk, locked files by another application (antivirus?) and other equally annoying thingsAlcoholism
Multiple processes and write locking could be a problem that needs to be addressed. This could lead you to an abstraction layer on top of your filesystem. And thus a bit more complexity and dependencies.Anorexia

© 2022 - 2024 — McMap. All rights reserved.