web-dev-qa-db-fra.com

une bonne et simple bibliothèque RPC pour les appels inter-processus?

J'ai besoin d'envoyer une (probablement une) commande unidirectionnelle simple de processus client à processus serveur avec des arguments de types C++ intégrés (la sérialisation est donc assez simple). C++, Windows XP +.

Je recherche une bibliothèque qui ne nécessite pas de configuration compliquée, qui offre une interface simple, qui ne nécessite pas des heures d'apprentissage, et qui n'a pas de restrictions d'utilisation commerciale. Solution simple pour un problème simple.

Boost.Interprocess est un niveau trop bas pour cette tâche simple car il ne fournit pas d'interface RPC. Les sockets sont probablement une surdose aussi parce que je n'ai pas besoin de communiquer entre machines. La même chose à propos de DCOM, CORBA et al. Des pipes nommés? Jamais utilisé, une bonne bibliothèque sur WinAPI? OpenMPI?

50
Andriy Tylychko

Je ne pense pas que les prises de courant sont vraiment excessives. Les alternatives ont toutes leurs propres problèmes et les sockets sont bien mieux supportés que les pipes nommées, la mémoire partagée, etc., car presque tout le monde les utilise. La vitesse des prises sur le système local n'est probablement pas un problème.

Il y a Apache Thrift:

http://incubator.Apache.org/thrift/

Quelques implémentations de RPC sont intégrées à la bibliothèque protobuf de Google en tant que mécanisme de marshaling:

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

Il y a XML-RPC:

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

Si vos messages sont vraiment simples, je pourrais envisager d'utiliser des paquets UDP, alors il n'y a pas de connexion à gérer.

17
Tim Sylvester

Vous pourriez aimer ZeroMQ pour quelque chose comme ça. Peut-être pas autant un RPC complet qu'un framework de messagerie d'octets bruts que vous pourriez utiliser pour créer un RPC. C'est simple, léger et avec une performance impressionnante. Vous pouvez facilement implémenter un RPC par dessus. Voici un exemple de serveur directement du manuel:

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

Cet exemple utilise tcp: //*.5555, mais utilise des techniques plus efficaces IPC si vous utilisez:

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

ou encore plus rapide protocole inter thread:

socket.bind("inproc://path.for.client.to.connect");
9
Imbrondir

Si vous n’avez besoin que de prendre en charge Windows, j’utiliserais le code RPC intégré de Windows, j’ai écrit deux articles introductifs à ce sujet:

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

Vous pouvez utiliser le protocole ncalrpc si vous avez uniquement besoin d'une communication interprocessus locale.

6
dalle

Boost.MPI . Simple, rapide, évolutif.

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

Si vous travaillez uniquement sur Windows et que vous avez vraiment besoin d'une interface C++, utilisez COM/DCOM. Il est basé sur RPC (à son tour sur DCE RPC). 

Son utilisation est extrêmement simple - à condition de prendre le temps d’apprendre les bases.

3
Ben

Je sais que nous sommes loin d’être faciles à utiliser. Mais bien sûr, vous pouvez vous en tenir à CORBA. Par exemple. ACE/TAO

2
mkaes

Vous n'avez probablement même pas besoin d'une bibliothèque. Windows possède un mécanisme IPC intégré dans ses API principales (windows.h). Vous pouvez en principe publier un message Windows dans la file de messages d'une fenêtre principale de processus différents. Windows définit même un message standard pour faire exactement cela: WM_COPYDATA.


Le processus d'envoi consiste essentiellement à:

Le processus de réception (fenêtre):

2
edgar.holleis

On me dit que RPC avec Raknet est gentil et simple. 

1
Goz

Aussi, vous pourriez regarder msgpack-rpc

Mettre à jour

Bien que Thrift/Protobuf soit plus flexible, je pense, mais il est nécessaire d’écrire du code dans un format spécifique. Par exemple, Protobuf a besoin d’un fichier .proto, qui peut être compilé avec un compilateur spécifique à partir d’un package, qui génèrera certaines classes. Dans certains cas, il peut être plus difficile que d’autres parties du code . Msgpack-rpc soient beaucoup plus simples. Il ne nécessite pas d'écrire du code supplémentaire. Voici un exemple:

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

Sortie

ID: 1
name: name

Vous trouverez des exemples plus compliqués ici https://github.com/msgpack/msgpack-rpc/tree/master/cpp/test

1
caentist

J'utilise XmlRpc C++ pour Windows trouvé ici

Vraiment facile à utiliser :) Mais le seul effet secondaire est que c'est seulement un client!

0
RvdK

Il y a aussi Microsoft Messaging Queuing , qui est assez simple à utiliser lorsque tous les processus sont sur la machine locale.

0
Chris O