c++ - ¿Alguna buena y simple biblioteca RPC para llamadas entre procesos?
interprocess (12)
Necesito enviar un (probablemente uno) comando simple de un solo sentido desde los procesos del cliente al proceso del servidor con argumentos de tipos C ++ incorporados (por lo que la serialización es bastante simple). C ++, Windows XP +.
Estoy buscando una biblioteca que no requiera una configuración complicada, que ofrezca una interfaz simple, no requiera horas o días de aprendizaje y no tenga restricciones de uso comercial. Solución simple para un problema simple.
Boost.Interprocess tiene un nivel demasiado bajo para esta tarea simple porque no proporciona una interfaz RPC. Los sockets también son una exageración porque no necesito comunicarme entre máquinas. Lo mismo sobre DCOM, CORBA et al. ¿Tuberías con nombre? Nunca los usé, ¿alguna buena biblioteca sobre WinAPI? OpenMPI?
Además, puede ver msgpack-rpc
Actualizar
Aunque Thrift / Protobuf son más flexibles, creo, pero se requieren para escribir algún código en formato específico. Por ejemplo, Protobuf necesita algún archivo .proto, que puede compilarse con un compilador específico del paquete, que genere algunas clases. En algunos casos, podría ser más difícil que otras partes del código. msgpack-rpc es mucho más simple. No requiere escribir un código adicional. Aquí hay un ejemplo:
#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;
}
Salida
ID: 1
name: name
Ejemplos más complicados que puedes encontrar aquí https://github.com/msgpack/msgpack-rpc/tree/master/cpp/test
Estoy usando XmlRpc C ++ para Windows encontrado aquí
Realmente fácil de usar :) ¡Pero el único efecto secundario es que este es solo un cliente!
La solución más simple para la comunicación entre procesos es usar el sistema de archivos. Las solicitudes y las respuestas se pueden escribir como archivos temporales. Puede elaborar una convención de nomenclatura para los archivos de solicitud y respuesta.
Esto no le dará el mejor rendimiento, pero tal vez será lo suficientemente bueno.
Me dijeron que RPC con Raknet es agradable y simple.
No creo que los enchufes sean excesivos. Todas las alternativas tienen sus propios problemas y los sockets son mucho más compatibles que los named pipes, la memoria compartida, etc., porque casi todos los usan. La velocidad de los enchufes en el sistema local probablemente no sea un problema.
Hay Apache Thrift:
http://incubator.apache.org/thrift/
Hay algunas implementaciones de RPC envueltas en la biblioteca de protobuf de Google como el mecanismo de clasificación:
https://github.com/google/protobuf/blob/master/docs/third_party.md#rpc-implementations
Hay XML-RPC:
http://xmlrpc-c.sourceforge.net/
Si sus mensajes son realmente simples, podría considerar el uso de paquetes UDP, entonces no hay conexiones para administrar.
Probablemente ni siquiera necesites una biblioteca. Windows tiene un mecanismo de IPC integrado profundamente en sus API principales (windows.h). Básicamente puede publicar un mensaje de Windows en la cola de mensajes de una ventana principal de procesos diferentes. Windows incluso define un mensaje estándar para hacer justamente eso: WM_COPYDATA.
- Documentación de MSDN en WM_COPYDATA
- Código de demostración de MSDN
- Más código de demostración, la siguiente response
El proceso de envío básicamente lo hace:
El proceso de recepción (ventana):
- En Vista y luego tiene que modificar su filtro de mensajes usando ChangeWindowsMessageEx
- Anular su WindowProc
- Para manejar el WM_COPYDATA entrante
Sé que estamos lejos de ser fáciles de usar. Pero, por supuesto, puedes apegarte a CORBA. Ej. ACE/TAO
Si está trabajando solo en Windows y realmente necesita una interfaz C ++, use COM / DCOM. Está basado en RPC (a su vez basado en DCE RPC).
Es extremadamente simple de usar, siempre que se tome el tiempo de aprender los conceptos básicos.
- ATL: http://msdn.microsoft.com/en-us/library/3ax346b7(VS.71).aspx
- Lenguaje de definición de interfaz: http://msdn.microsoft.com/en-us/library/aa367091(VS.85).aspx
Si solo necesita soportar Windows, usaría el RPC integrado de Windows. He escrito dos artículos introductorios sobre esto:
http://www.codeproject.com/KB/IP/rpcintro1.aspx
http://www.codeproject.com/KB/IP/rpcintro2.aspx
Puede usar el protocolo ncalrpc
si solo necesita comunicación local entre procesos.
También hay Microsoft Messaging Queuing , que es bastante sencillo de usar cuando todos los procesos están en la máquina local.
Boost.MPI . Simple, rápido, escalable.
#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());
}
Es posible que le guste ZeroMQ para algo como esto. Tal vez no tanto un RPC completo, como un marco de mensajería de bytes sin procesar que podría usar para hacer un RPC. Es simple, ligero y con un rendimiento impresionante. Usted puede implementar fácilmente una RPC además de eso. Aquí hay un servidor de ejemplo directamente del 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;
}
Este ejemplo usa tcp: //*.5555, pero usa técnicas de IPC más eficientes si usa:
socket.bind("ipc://route.to.ipc");
o incluso un protocolo entre hilos más rápido:
socket.bind("inproc://path.for.client.to.connect");