Next: Type declarations in
the
Introduction
Remote Procedure Call (RPC) is a powerful mechanism for client/server and distributed computing in general.
PowerRPC is a powerful RPC development tool that help unleash the full power of RPC programming. It makes arbitrary C functions callable across process boundaries over a TCP/IP network, and it is very easy to learn and use.
PowerRPC mainly consists of the powerRPC IDL compiler and the powerRPC runtime time library. Given an interface description in a form almost identical to C function declarations, the IDL compiler generates client and server stub code - the code handles the networking and server dispatching, for generic multi-argument C functions. The arguments of the C functions can be of IN, OUT or INOUT directions, and they can be any complex C data types such as structs, linked list, unions, multi-dimensional arrays, etc. The problem of transporting data between different architectures are solved by the XDR mechanism, this way, an RPC server can be called by clients from any platform.
Since one of the main design goal of powerRPC is to bring the power of RPC programming to general C/C++ programmers, it is made very easy to use. In powerRPC, the programmer is insulated from network programming at TCP/IP level and the ONC RPC level. The programmer only needs to provide an interface description and code their implementation. A programmer without any prior experience of network and RPC programming experience can write sophisticated, robust and efficient powerRPC programs in a very short time.
PowerRPC is also designed to provide elegant solutions to common problems in client/server computing. For example, it allows you to create multi-tasking or multi-threading servers, it supports asynchronous server,... and you can enable these features simply by specifying properties in the interface description.
One of the main component of powerRPC is its IDL compiler. Given an interface definition, powerRPC generates the RPC stub code for network transport and server dispatch. An interface definition language (IDL) file declares the C functions provided by an RPC interface and the data types used by these functions as arguments or return values. An example of a the IDL file looks like the quote RPC interface shown below, whose purpose is to allow a client (the RPC caller) to get the stock quotes for a given ticker symbol,
% cat quote.idl typedef struct { char Ticker[8]; double Low; double High; double Close; } stkQuote; interface quote { int getQuote(inout stkQuote * pQuote); } 0x12345;
There is nothing special about the typedef--it is pure C. The powerRPC keyword interface followed by identifier quote starts the declaration of an RPC interface, which encloses a set of function declarations in curly braces. Here we have only one function, getQuote(), which takes a pointer to stkQuote. The inout keyword specifies the direction of the argument pQuote. In this case, the argument is used for both input and output - the client sends the struct over to the server, the server uses the Ticker field to find quotes, and sends them back. The integer 0x12345 is just an identification number for this RPC interface, which maps to the program number in ONC RPC.
We compile the interface with the command,
% powerRPC quote.idl Five files will be generated,
quote.h | Header to be included by the client and server. |
quote_svc.c | Server stub, it calls the server implementation of getQuote(). |
quote_cln.c | Client stub, it defines the getQuote() function for the client, this function is the interface to the server's getQuote() function. |
quote_xdr.c | XDR routines used by both the client and server to encode and decode the arguments and return values. |
quote.mak | A makefile template. |
Our lucky programmer now needs to provide the getQuote() function for the server, assuming it is in the file quote_impl.c, it may look like this,
%cat quote_impl.c #include "quote.h" int getQuote( stkQuote * quote) { /* let's just return some good value. */ quote->Low = 30; quote->High = 35; quote->Close = 34; return 0; }
Now, we can compile and run the server
,
% cc -o quoteserv quote_svc.c quote_xdr.c quote_impl.c -lpwrpc % quoteserv
The server starts up and announces its registration with the portmapper (or rpcbind on SYSVR4). Now the getQuote() function is ``exposed" to the network and is callable by an authenticated client.
We now write a simple client program, in file quote_call.c,
% cat quote_call.c #include "quote.h" int main(int argc, char**argv) { stkQuote q; if(quote_bind(argv[1], 0,0,0)==NULL) { printf("Fail connect to server on host %s\n", argv[1]); exit(1); } strcpy(q.Ticker, argv[2]); /* make the RPC call */ if(getQuote(&q) <0) { printf("Fail get quote for %s\n", q.Ticker); } else { printf("Quote for %s (LOW, HIGH, CLOSE):\n", q.Tikcer); printf(" %f %f %f\n", q.Low, q.High, q.Close); } quote_unbind(0); }
We used three functions produced by powerRPC, quote_bind() binds the RPC connection to the server, quote_unbind() close the RPC connection, and getQuote() calls the RPC function.
We compile the quote client,
% cc -o quoteclnt quote_cln.c quote_xdr.c quote_call.c
Suppose quoteserv is running on host eagle, we run the client as follows
% quoteclnt eagle <ANY TICKER>
You will see the set of values printed on client's terminal.
Let's summarize the steps in powerRPC programming,
Starting from next chapter, we will learn more about powerRPC IDL.
Type declarations...
Type declarations in the powerRPC IDL
Interface declarations in the powerRPC IDL
Copyright (C) Netbula LLC, 1996