Sometimes, we want an RPC to return immediately, and let the server return the results to the client asynchronously. For example, if it takes the quote server a long time to query a database to get the data, for reasons such as the large number of requests, we should let the client to continue to do other things and get the result later when it is ready.
With powerRPC this can be achieved easily. By setting the NON_BLOCKING
property to true, an RPC call would return before the server function gets
called. To receive the result later, the client can register a collection
service, which is an RPC interface. When the server get the result, it calls
upon this RPC registered by the client
to send the result back.
In this example, we demonstrate how to make our quote RPC asynchronous. We have two RPC interfaces defined in back.idl and over.idl. The client main function looks like this,
#include "over.h" #include "back.h" #include <signal.h> #include <rpc/pmap_clnt.h> main(int argc, char **argv) { char myhost[1024]; if (argc < 3) { printf("usage: %s hostname ticker\n", argv[0]); exit(1); } pw_serv_init(); back_1_unmap(0, 0); if (!back_1_reg(RPC_ANYSOCK, BACK, BACK_1, IPPROTO_TCP)) { printf("fail registering \n"); exit(0); } pw_serv_async_enable(); if (!over_bind(argv[1], 0, 0, 0)) { printf("fail connect to OVER server.\n"); exit(0); } gethostname(myhost, 1023); getQuote(myhost, argv[2]); printf("Returned from 1st getQuote... now do something else ..\n"); getQuote(myhost, argv[2]); printf("Returned from 2st getQuote... now do something else ..\n"); getQuote(myhost, argv[2]); printf("Returned from 3rd getQuote... now do something else ..\n"); while (1) { printf("happily doing ....\n"); sleep(10); } }
In the above, the client set up an asynchronous RPC back.
Then it makes two calls of getQuote(), both return
immediately. This getQuote() call is different from the one we studied
earlier: it has an additional argument myhost.
When the server receives the call,
it gets the quote, and calls back myhost to send the results.
The client enters a while loop, pretending to do other work,
when the server's callback arrives, the client will be interrupted,
and the returnQuote() implementation is called.
The asynchronous behavior of the client's RPC is enabled
by the pw_serv_async_enable() powerRPC library call
{.
Below is the server's code.
#include "back.h" #include <stdlib.h> /* This is an asynchronous call, the client sends over its hostname, after receiving the request, the server replies back to the client immediately. Then client and server reverse their roles, the server make the RPC returnQuote() to send the result to the client, who is supposed to acting as a BACK server waiting for the result. */ void getQuote(char *caller_host, char Ticker[8]) { stkQuote quote; printf("Called by %s\n", caller_host); printf("sleep for a while ....\n"); sleep(6); if (!back_bind(caller_host, 0, 0, 0)) { printf("client is not there!\n"); return; } strcpy(quote.Ticker, Ticker); /* find the quotes */ quote.Low = rand() % 100; quote.High = rand() % 100; quote.Close = rand() % 100; printf("now sending back quote ....\n"); printf("%s %f %f %f\n", quote.Ticker, quote.Low, quote.High, quote.Close); returnQuote("e); back_unbind(0); }