Remote procedure call (RPC) is a technology that allows a computer program to cause a subroutine or procedure to execute in another address

space (commonly on another computer on a shared network) without the programmer explicitly coding the details for this remote interaction. That is, the programmer would write essentially the same code whether the subroutine is local to the executing program, or remote.

How RPC Works
An RPC is analogous to a function call. Like a function call, when an RPC is made, the calling arguments are passed to the remote procedure and the caller waits for a response to be returned from the remote procedure. The below figure shows the flow of activity that takes place during an RPC call between two networked systems. The client makes a procedure call that sends a request to the server and waits. The thread is blocked from processing until either a reply is received, or it times out. When the request arrives, the server calls a dispatch routine that performs the requested service, and sends the reply to the client. After the RPC call is completed, the client program continues. RPC specifically supports network applications.

Each version contains a a number of procedures that can be called remotely. version number. • Retrieve information by calling a query.Remote Procedure Calling Mechanism A remote procedure is uniquely identified by the triple: (program number. rpcgen rpcgen exists as a standalone executable compiler that reads special files denoted by a . Each version consists of a collection of procedures which are available to be called remotely. and data types of parameters and return arguments. For the protocol you must identify the name of the service procedures. So to compile a RPCL file you simply do . Each procedure has a procedure number. which will be quicker than previous approach. uses its own language (RPC language or RPCL) which looks very similar to preprocessor directives. A program may consist of one or more versions. each of which has a unique procedure number. procedure number) The program number identifies a group of related remote procedures. The protocol compiler reads a definition and automatically generates client and server stubs. Defining the Protocol The easiest way to define and generate the protocol is to use a protocol complier such as rpcgen which we discuss is Chapter 33. The communication protocol is achieved by generated stubs and these stubs and rpc (and other libraries) will need to be linked in. RPC Application Development The RPC alternative is to Establish an server on the remote machine that can respond to queries. Version numbers enable multiple versions of an RPC protocol to be available simultaneously. • To develop an RPC application the following steps are needed: • • • Specify the protocol for client server communication Develop the client program Develop the server program The programs will be compiled seperately.x prefix.

Create a file named rand.rpcgen rpcprog.If necessary XDR (external data representation) rpcprog.x The following four files should be generated: . We will briefly discuss these below before expanding the most common of these in later chapters. The client application calls the remote procedure.the header file needed for any XDR filters. The external data representation (XDR) is an data abstraction needed for machine independent communication.the server stub rpcprog_xdr. /* service #1 */ double GET_NEXT_RANDOM ( void ) = 2. pass any required data and will receive the returned data. There are several levels of application interfaces that may be used to develop RPC applications. /* service #2 */ } = 1.x This will generate possibly four files: • • • • rpcprog_clnt. Defining Client and Server Application Code We must now write the client and application code.c -.c -.x with the following context: /* rand. } = 0x30000000. /* program # */ Generate the program templates by $rpcgen -C -a rand. They must communicate via procedures and data types specified in the Protocol.c -. The service side will have to register the procedures that may be called by the client and receive and return any data required for processing.the client stub rpcprog_svc.h filters -. The client and server need not be machines of the same type.x */ program RADN_PROG { version RAND_VERS { void INITIALIZE_RANDOM ( long ) = 1.

c and rand_server. rand.c are the client and server programs that need to be edited to accomplish the goals. rand_client. The original source code of rand_server. rand_svc.c.rand.c .Makefile.c The programs rand_client.c.c. rand_clnt.h. rand_server.

} ./* * This is sample code generated by rpcgen.h" void * initialize_random_1_svc(long *argp. * These are only templates and you can use them * as a guideline for developing your own functions. struct svc_req *rqstp) { static double result. struct svc_req *rqstp) { static char * result. */ #include "rand. /* * insert server code here */ return &result. } double * get_next_random_1_svc(void *argp. /* * insert server code here */ return (void *) &result.

} DEBUG clnt_destroy (clnt). exit (0). if (argc < 2) { printf ("usage: %s server_host\n". char *get_next_random_1_arg. #ifndef DEBUG clnt = clnt_create (host. if (result_2 == (double *) NULL) { clnt_perror (clnt. exit (1). } host = argv[1]. RADN_PROG. clnt). long initialize_random_1_arg. char *argv[]) { char *host. "udp"). if (result_1 == (void *) NULL) { clnt_perror (clnt. void *result_1. exit (1). RAND_VERS.The original source code of rand_client.h" void radn_prog_1(char *host) { CLIENT *clnt. "call failed"). } The modified source code of rand_client. } result_2 = get_next_random_1((void*)&get_next_random_1_arg. double *result_2. } /* DEBUG */ result_1 = initialize_random_1(&initialize_random_1_arg. radn_prog_1 (host). if (clnt == NULL) { clnt_pcreateerror (host).c . clnt).c /* * This is sample code generated by rpcgen. argv[0]). */ #include "rand. "call failed"). * These are only templates and you can use them * as a guideline for developing your own functions. /* DEBUG */ #endif #ifndef #endif } int main (int argc.

radn_prog_1 (host). RADN_PROG. int main (int argc./* * This is sample code generated by rpcgen. printf(" %f. */ #include "rand. x ). "call failed"). printf("\n twenty random numbers "). if (argc < 2) { printf ("usage: %s server_host\n". long initialize_random_1_arg. ++i ){ x = radn_prog_1 (host). if (clnt == NULL) { clnt_pcreateerror (host). RAND_VERS. } . #ifndef DEBUG clnt = clnt_create (host. char *get_next_random_1_arg. clnt). double x. /* DEBUG */ #endif #ifndef #endif } return *result_2. if (result_2 == (double *) NULL) { clnt_perror (clnt. i < 20. exit (1).h" double radn_prog_1(char *host) { CLIENT *clnt. exit (1). } host = argv[1]. int i. } result_2 = get_next_random_1((void*)&get_next_random_1_arg. } /* DEBUG */ result_1 = initialize_random_1(&initialize_random_1_arg. "call failed"). char *argv[]) { char *host. "udp"). clnt). * These are only templates and you can use them * as a guideline for developing your own functions. double *result_2. if (result_1 == (void *) NULL) { clnt_perror (clnt. argv[0]). void *result_1. ". for ( i = 0. } DEBUG clnt_destroy (clnt). } exit (0).

} host = argv[1]. double x. if (clnt == NULL) { clnt_pcreateerror (host). char *get_next_random_1_arg.h" double radn_prog_1(char *host) { CLIENT *clnt. */ #include "rand. clnt). if (result_2 == (double *) NULL) { clnt_perror (clnt. /* DEBUG */ #endif #ifndef #endif } return *result_2. * These are only templates and you can use them * as a guideline for developing your own functions. if (result_1 == (void *) NULL) { clnt_perror (clnt. long initialize_random_1_arg. } /* DEBUG */ result_1 = initialize_random_1(&initialize_random_1_arg. clnt).c /* * This is sample code generated by rpcgen. } DEBUG clnt_destroy (clnt). char *argv[]) { char *host. double *result_2. "call failed"). RADN_PROG. int main (int argc. "udp").The modified source code of rand_client. radn_prog_1 (host). exit (1). RAND_VERS. "call failed"). #ifndef DEBUG clnt = clnt_create (host. void *result_1. if (argc < 2) { printf ("usage: %s server_host\n". argv[0]). exit (1). } result_2 = get_next_random_1((void*)&get_next_random_1_arg. .

o(.000001. } exit (0). x ). struct svc_req *rqstp) { static double result.h" #include <stdlib. } The random generator result = ((double)(rand()%1000000))*0.c as follows. ".c $ make -f Makefile. Some error messages may happen while executing the command of $ make -f Makefile.h> …… …… double * get_next_random_1_svc(void *argp. printf("\n twenty random numbers ").o rand_client.c Modify the rand_server. #include "rand.000001 will generates the random numbers which 0 < results < 1.o -lnsl rand_client. printf(" i. return &result.rand The two executable files rand_client and rand_server will be generated. Compile and link the programs with $g++ -c rand_server. for ( i = 0. ++i ){ x = radn_prog_1 (host).rand The error messages shows as following: cc -g -c -o rand_clnt. result = ((double)(rand()%1000000))*0. i < 20.eh_frame+0x11): undefined reference to `__gxx_personality_v0' . } The modified source code of rand_server.c $g++ -c rand_client.c cc -g -o rand_client rand_clnt.o rand_clnt.

/rand_client your_host_name 20 numbers should be printed by the client.2 And then start the client in another window by $.o cannot be linked. The server part: . S7./rand_server S7. another X-window need to be opened.collect2: ld returned 1 exit status make: *** [rand_client] Error 1 which means the rand_clnt.rand again. This problem can be solved by using the command: $g++ -o rand_client rand_clnt. Following are the scripts that executed the programs of rand_server and rand_client on localhost.o –lnsl And then rerun the command $ make -f Makefile.o and rand_client.o rand_client. The numbers are generated by the server.1 To start the server in one window by $. In order to run the two executable files simultaneously.

The client part: .

}. Compile the above RPCL file . }=0x30000000. int hour.EXAMPLE: Date. int min. program DATE_PROG{ version DATE_VERS{ tmp timed(void)=1. }=1.x: struct tmp{ int sec.

} #endif /* DEBUG */ result_1 = timed_1((void*)&timed_1_arg.x Date_client: * This is sample code generated by rpcgen. */ #include "date.result_1->min). printf("\n Min :%d". tmp *result_1.rpcgen date. * These are only templates and you can use them * as a guideline for developing your own functions. #ifndef DEBUG clnt = clnt_create (host. DATE_VERS. if (result_1 == (tmp *) NULL) { clnt_perror (clnt.result_1->hour). #endif /* DEBUG */ } int main (int argc. } printf("\n Hour:%d". char *timed_1_arg.result_1->sec). "udp"). char *argv[]) .h" void date_prog_1(char *host) { CLIENT *clnt. printf("\n Sec :%d". exit (1). clnt). if (clnt == NULL) { clnt_pcreateerror (host). DATE_PROG. #ifndef DEBUG clnt_destroy (clnt). "call failed").

.{ char *host. } Date_server: /* * This is sample code generated by rpcgen. * These are only templates and you can use them * as a guideline for developing your own functions.sec=time1->tm_sec. date_prog_1 (host). struct tm *time1. argv[0]). exit (1). if (argc < 2) { printf ("usage: %s server_host\n". time_t t. result.h> tmp * timed_1_svc(void *argp. */ #include "date.h" # include<time. } host = argv[1]. t=time(NULL). struct svc_req *rqstp) { static tmp result. exit (0). time1=localtime(&t).

result.result. 2. Implement a RPC program to .min=time1->tm_min. Implement a RPC program to find the square of a given number. } Exercises: 1.hour=time1->tm_hour. /* * insert server code here */ return &result.

Sign up to vote on this title
UsefulNot useful