可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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?
回答1:
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.
回答2:
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");
回答3:
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.
回答4:
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());
}
回答5:
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.
- ATL: http://msdn.microsoft.com/en-us/library/3ax346b7(VS.71).aspx
- Interface Definition Language: http://msdn.microsoft.com/en-us/library/aa367091(VS.85).aspx
回答6:
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.
- MSDN docu on WM_COPYDATA
- MSDN demo code
- More demo code the following StackOverflow response
The sending process basically does:
The receiving process (window):
- On Vista and later has to modify its message filter using ChangeWindowsMessageEx
- Override its WindowProc
- In order to handle the incoming WM_COPYDATA
回答7:
I know that we are far away from easy to use. But of course you can stick to CORBA. E.g. ACE/TAO
回答8:
I'm told RPC with Raknet is nice and simple.
回答9:
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
回答10:
I'm using XmlRpc C++ for Windows found here
Really easy to use :) But the only side effect that this is only a client!
回答11:
There's also Microsoft Messaging Queueing, which is fairly straightforward to use when all processes are on the local machine.
回答12:
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.