views:

30

answers:

1

I have a remote server which handles various different commands, one of which is an event fetching method.

The event fetch returns right away if there is 1 or more events listed in the queue ready for processing. If the event queue is empty, this method does not return until a timeout of a few seconds. This way I don't run into any HTTP/socket timeouts. The moment an event becomes available, the method returns right away. This way the client only ever makes connections to the server, and the server does not have to make any connections to the client. This event mechanism works nicely. I'm using the boost library to handle queues, event notifications, etc.

Here's the problem. While the server is holding back on returning from the event fetch method, during that time, I can't issue any other commands. In the source code, XmlRpcDispatch.cpp, I'm seeing in the "work" method, a simple loop that uses a blocking call to "select". Seems like while the handling of a method is busy, no other requests are processed.

Question: am I not seeing something and can XmlRpcpp (xmlrpc++) handle multiple requests asynchronously? Does anyone know of a better xmlrpc library for C++? I don't suppose the Boost library has a component that lets me issue remote commands? I actually don't care about the XML or over-HTTP feature. I simply need to issue (asynchronous) commands over TCP in any shape or form? I look forward to any input anyone might offer.

+1  A: 

I had some problems with XMLRPC also, and investigated many solutions like GSoap and XMLRPC++, but in the end I gave up and wrote the whole HTTP+XMLRPC from scratch using Boost.ASIO and TinyXML++ (later I swaped TinyXML to expat). It wasn't really that much work; I did it myself in about a week, starting from scratch and ending up with many RPC calls fully implemented.

Boost.ASIO gave great results. It is, as its name says, totally async, and with excellent performance with little overhead, which to me was very important because it was running in an embedded environment (MIPS).

Later, and this might be your case, I changed XML to Google's Protocol-buffers, and was even happier. Its API, as well as its message containers, are all type safe (i.e. you send an int and a float, and it never gets converted to string and back, as is the case with XML), and once you get the hang of it, which doesn't take very long, its very productive solution.

My recomendation: if you can ditch XML, go with Boost.ASIO + Protobuf
If you need XML: Boost.ASIO + Expat

Doing this stuff from scratch is really worth it.

Gianni
I'm considering using boost's asio. I'm hoping I can write ints and strings to the stream from the C++ end, and receive it on the Java end using DataInputStream reads.
Mike
@Mike then I strongly suggest using XML or protobuf; because there might be a few gotchas when doing that, and they'll both take care of that for you.
Gianni
@Gianni. Running into problem with asio. I have an event queue that, when empty, and when queried using socket communication, waits a while before return and reporting the queue is empty, or wakes up and reports the queue's contents when an even becomes available.So the client has two connections to the server. One to issues instructions, the other to get (wait for) events.The problem is that when using asio, when one session is waiting, the other isn't accepting any commands.So in other words, one session hogs the other.So much for it being asynchronous?
Mike
@Mike Well, it *is* still async, it is just that in your case you'll need two ASIO queues, or `boost::asio::io_service`. Just do that: create a new for each `io_service` socket you have. It should as trivial as it sounds and solve your problem.
Gianni
@Gianni. Ok, after endless horsing around and not finding any clear documentation anywhere, I got nowhere with starting threads upon new sockets.Then I found this: http://stackoverflow.com/questions/1982595/boost-asio-io-service-run-questionI then clued in that this io_service is a working task that tries to take work as it finds it, in a way where you can have multiple threads call for work by calling run from created worked threads.So, instead of creating threads on demand (which I suppose is possible as well), what I did is create two threads, each calling run on the one io_service.
Mike
@Gianni. I got confused by your message: " create a new for each io_service socket you have". Create a new what? I thought maybe, create a new io_service for each socket. So I started instantiating an io_service for each incoming session, and call run() on a new thread.I don't know what I did wrong, but I couldn't get it to work.What did work was just one single modification by calling run() from two threads (in my case).Bit of a learning curve with boost. It's more comparable with Java's socket channels I guess.Thanks for the hints though - it did point me in the right direction.
Mike