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?

Andriy Tylychko
  • 15,967
  • 6
  • 64
  • 112
  • 1
    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).aspx – Logan Capaldo Mar 22 '11 at 23:16
  • 1
    Oops http://msdn.microsoft.com/en-us/library/aa378651(v=VS.85).aspx – Logan Capaldo Mar 23 '11 at 00:34

12 Answers12

20

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.

KindDragon
  • 6,558
  • 4
  • 47
  • 75
Tim Sylvester
  • 22,897
  • 2
  • 80
  • 94
  • 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) – Andriy Tylychko Mar 23 '11 at 00:40
  • btw, is it 100% guaranteed that UDP packet cannot be lost if sent to local process? – Andriy Tylychko Apr 02 '11 at 16:56
  • @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. – Tim Sylvester Apr 02 '11 at 19:51
  • @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. – Tim Sylvester Apr 02 '11 at 19:53
  • 1
    @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 dropped – nos Apr 29 '11 at 00:26
  • @nos 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. – Tim Sylvester Apr 29 '11 at 01:08
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");
Imbrondir
  • 666
  • 6
  • 12
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.

dalle
  • 18,057
  • 5
  • 57
  • 81
  • 1
    nice work, haven't you thought about developing a C++ library over MS RPC? – Andriy Tylychko Mar 30 '11 at 15:46
  • 1
    @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. – dalle Mar 30 '11 at 19:30
  • 2
    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 http://msdn.microsoft.com/en-us/library/aa230583%28v=vs.60%29.aspx – edgar.holleis Mar 31 '11 at 09:55
  • @dalle, how is you success in search? – Dzmitry Lahoda Aug 05 '13 at 13:43
  • @DzmitryLahoda: We have found several different alternatives. RPC over MessagePack, RPC over Protocol Buffers, JSON-RPC, Thrift, XML-RPC. – dalle Aug 05 '13 at 14:48
  • 1
    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. – Niki Jan 16 '18 at 08:57
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());
}
log0
  • 10,489
  • 4
  • 28
  • 62
  • 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? – Andriy Tylychko Apr 02 '11 at 16:43
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.

Ben
  • 34,935
  • 6
  • 74
  • 113
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):

Community
  • 1
  • 1
edgar.holleis
  • 4,803
  • 2
  • 23
  • 27
2

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

mkaes
  • 13,781
  • 10
  • 52
  • 72
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

asukharev
  • 477
  • 6
  • 12
  • Whilst this may theoretically answer the question, [it would be preferable](http://meta.stackexchange.com/q/8259) to include the essential parts of the answer here, and provide the link for reference. – Spontifixus Jan 22 '13 at 22:11
  • And the streaming feature looks very nice – rox Apr 20 '17 at 05:42
1

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

Goz
  • 61,365
  • 24
  • 124
  • 204
  • 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 impressive – Andriy Tylychko Mar 22 '11 at 23:35
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!

RvdK
  • 19,580
  • 4
  • 64
  • 107
0

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

Chris O
  • 5,017
  • 3
  • 35
  • 42
-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.

StackedCrooked
  • 34,653
  • 44
  • 154
  • 278
  • 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 things – Andriy Tylychko Mar 30 '11 at 15:28
  • 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. – Derick Schoonbee Apr 02 '11 at 09:17