0

I would like to have a class written in C++ that acts as a remote procedure call server.

I have a large (over a gigabyte) file that I parse, reading in parameters to instantiate objects which I then store in a std::map. I would like the RPC server to listen for calls from a client, take the parameters passed from the client, look up an appropriate value in the map, do a calculation, and return the calculated value back to the client, and I want it to serve concurrent requests -- so I'd like to have multiple threads listening. BTW, after the map is populated, it does not change. The requests will only read from it.

I'd like to write the client in Python. Could the server just be an HTTP server that listens for POST requests, and the client can use urllib to send them?

I'm new to C++ so I have no idea how to write the server. Can anyone point me to some examples?

John Thompson
  • 1,674
  • 1
  • 20
  • 35
  • Why C++? You could simply write a python server (http://stackoverflow.com/questions/14088294/multithreaded-web-server-in-python). If your calculation is time consuming or in C++ just wrap it using ctypes – user1827356 Jul 17 '13 at 22:46
  • You can't do threads in Python, only multiprocessing -- so I can't have the threaded map thing that I want to have if the server is in Python. – John Thompson Jul 17 '13 at 23:01
  • @JohnPeterThompsonGarcés: First, yes, you _can_ do threads in Python. If you just need concurrent requests, you're done. If you need concurrent CPU-bound requests, where the CPU-bound code is your C++ class, just make your wrapper release the GIL around calls into that class. And while we're at it, it's not that hard to share a `std::map` between processes. – abarnert Jul 17 '13 at 23:04
  • Wouldn't any sharing between processes require a lot of message passing? I want to use shared memory. You talk about releasing the GIL. That sounds complicated. – John Thompson Jul 17 '13 at 23:10
  • You can share the map across threads, just like you would in C++. For GIL, I've found this helpful (http://docs.python.org/release/1.5.2/api/threads.html) In particular - Py_BEGIN_ALLOW_THREADS ...Do some blocking I/O operation... Py_END_ALLOW_THREADS – user1827356 Jul 17 '13 at 23:37

2 Answers2

0

Maybe factors can affect the selection.

One solution is to use fastcgi.

Client sends HTTP request to HTTP server that has fastCGI enabled. HTP server dispatch the request to your RPC server via the fastcgi mechanism. RPC server process and generates response, and sends back to http server. http server sends the response back to your client.

ROTOGG
  • 1,106
  • 1
  • 7
  • 17
0

If you must write the server in C++, and you have no idea how to do so, you definitely want to use a framework.

There are many choices out there, and StackOverflow is not a good place to ask for opinions about different choices. But to give you one example, JsonRpc-Cpp lets you implement a JSON-RPC (over either raw TCP or HTTP) server in about 10 lines of code, plus a line of boilerplate for each RPC you want to expose. Much easier than writing a server from scratch.

So, here's an example server:

#include <cstdlib>
#include <jsonrpc.h>

class Service {
public:
    bool echo(const Json::Value &root, Json::Value &response) {
        response["jsonrpc"] = "2.0";
        response["id"] = root["id"];
        Json::Value result;
        result["params"] = root["params"];
        response["result"] = result;
        return response;
    }
}

int main(int argc, char *argv[]) {
    int port = std::atoi(argv[1]); // add some error handling here...

    Json::Rpc::TcpServer server("127.0.0.1", port);
    Service service;
    server.AddMethod(new Json::Rpc::RpcMethod<Service>(service,
                     &Service::echo, "echo");
    server.Bind(); // add error handling again
    server.Listen();
    while(true) server.WaitMessage(1000);
}

However, it will probably be even easier if you write the server in Python, or use a WSGI web server and write a service in Python, and call the C++ code from Python (whether via ctypes, or by building a wrapper with something like Cython or SIP).

Here's the same server in Python using bjsonrpc:

import bjsonrpc

class Service(bjsonrpc.handlers.BaseHandler):
    def echo(self, *args):
        return {'params': args}

server = bjsonrpc.createserver(handler_factory = Service)
server.serve()
abarnert
  • 354,177
  • 51
  • 601
  • 671