Remote Procedure Call
Remote Procedure Call
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.
Remote Procedure Calling Mechanism A remote procedure is uniquely identified by the triple: (program number, version number, procedure number) The program number identifies a group of related remote procedures, each of which has a unique procedure number. A program may consist of one or more versions. Each version consists of a collection of procedures which are available to be called remotely. Version numbers enable multiple versions of an RPC protocol to be available simultaneously. Each version contains a a number of procedures that can be called remotely. Each procedure has a procedure number.
Specify the protocol for client server communication Develop the client program Develop the server program
The programs will be compiled seperately. The communication protocol is achieved by generated stubs and these stubs and rpc (and other libraries) will need to be linked in.
exists as a standalone executable compiler that reads special files denoted by a .x prefix.
rpcgen rpcprog.x
filters -- the header file needed for any XDR filters. The external data representation (XDR) is an data abstraction needed for machine independent communication. The client and server need not be machines of the same type.
/* rand.x */ program RADN_PROG { version RAND_VERS { void INITIALIZE_RANDOM ( long ) = 1; /* service #1 */ double GET_NEXT_RANDOM ( void ) = 2; /* service #2 */ } = 1;
} = 0x30000000;
/* program # */
Generate the program templates by $rpcgen -C -a rand.x The following four files should be generated:
The programs rand_client.c and rand_server.c are the client and server programs that need to be edited to accomplish the goals.
/*
* This is sample code generated by rpcgen. * These are only templates and you can use them * as a guideline for developing your own functions. */ #include "rand.h" void * initialize_random_1_svc(long *argp, struct svc_req *rqstp) { static char * result; /* * insert server code here */ return (void *) &result; } double * get_next_random_1_svc(void *argp, struct svc_req *rqstp) { static double result; /* * insert server code here */ return &result; }
#endif
#ifndef #endif }
int main (int argc, char *argv[]) { char *host; if (argc < 2) { printf ("usage: %s server_host\n", argv[0]); exit (1); } host = argv[1]; radn_prog_1 (host); exit (0); }
/* * This is sample code generated by rpcgen. * These are only templates and you can use them * as a guideline for developing your own functions. */ #include "rand.h" double radn_prog_1(char *host) { CLIENT *clnt; void *result_1; long initialize_random_1_arg; double *result_2; char *get_next_random_1_arg; #ifndef DEBUG clnt = clnt_create (host, RADN_PROG, RAND_VERS, "udp"); if (clnt == NULL) { clnt_pcreateerror (host); exit (1); } /* DEBUG */ result_1 = initialize_random_1(&initialize_random_1_arg, clnt); if (result_1 == (void *) NULL) { clnt_perror (clnt, "call failed"); } result_2 = get_next_random_1((void*)&get_next_random_1_arg, clnt); if (result_2 == (double *) NULL) { clnt_perror (clnt, "call failed"); } DEBUG clnt_destroy (clnt); /* DEBUG */
#endif
#ifndef #endif }
return *result_2;
int main (int argc, char *argv[]) { char *host; if (argc < 2) { printf ("usage: %s server_host\n", argv[0]); exit (1); } host = argv[1]; radn_prog_1 (host); double x; int i; printf("\n twenty random numbers "); for ( i = 0; i < 20; ++i ){ x = radn_prog_1 (host); printf(" %f, ", x ); } exit (0); }
#endif
#ifndef #endif }
return *result_2;
int main (int argc, char *argv[]) { char *host; if (argc < 2) { printf ("usage: %s server_host\n", argv[0]); exit (1); } host = argv[1]; radn_prog_1 (host); double x;
int i; printf("\n twenty random numbers "); for ( i = 0; i < 20; ++i ){ x = radn_prog_1 (host); printf(" %f, ", x ); } exit (0); }
The random generator result = ((double)(rand()%1000000))*0.000001 will generates the random numbers which 0 < results < 1.
Compile and link the programs with $g++ -c rand_server.c $g++ -c rand_client.c $ make -f Makefile.rand The two executable files rand_client and rand_server will be generated. Some error messages may happen while executing the command of $ make -f Makefile.rand The error messages shows as following: cc -g -c -o rand_clnt.o rand_clnt.c cc -g -o rand_client rand_clnt.o rand_client.o -lnsl rand_client.o(.eh_frame+0x11): undefined reference to `__gxx_personality_v0'
collect2: ld returned 1 exit status make: *** [rand_client] Error 1 which means the rand_clnt.o and rand_client.o cannot be linked. This problem can be solved by using the command: $g++ -o rand_client rand_clnt.o rand_client.o lnsl And then rerun the command $ make -f Makefile.rand again. In order to run the two executable files simultaneously, another X-window need to be opened. S7.1 To start the server in one window by $./rand_server S7.2 And then start the client in another window by $./rand_client your_host_name 20 numbers should be printed by the client. The numbers are generated by the server.
Following are the scripts that executed the programs of rand_server and rand_client on localhost.
EXAMPLE:
Date.x: struct tmp{ int sec; int min; int hour; }; program DATE_PROG{ version DATE_VERS{ tmp timed(void)=1; }=1; }=0x30000000; Compile the above RPCL file
rpcgen date.x
Date_client: * This is sample code generated by rpcgen. * These are only templates and you can use them * as a guideline for developing your own functions. */ #include "date.h" void date_prog_1(char *host) { CLIENT *clnt; tmp *result_1; char *timed_1_arg; #ifndef DEBUG clnt = clnt_create (host, DATE_PROG, DATE_VERS, "udp"); if (clnt == NULL) { clnt_pcreateerror (host); exit (1); } #endif /* DEBUG */ result_1 = timed_1((void*)&timed_1_arg, clnt); if (result_1 == (tmp *) NULL) { clnt_perror (clnt, "call failed"); } printf("\n Hour:%d",result_1->hour); printf("\n Min :%d",result_1->min); printf("\n Sec :%d",result_1->sec); #ifndef DEBUG clnt_destroy (clnt); #endif /* DEBUG */ } int main (int argc, char *argv[])
{ char *host; if (argc < 2) { printf ("usage: %s server_host\n", argv[0]); exit (1); } host = argv[1]; date_prog_1 (host); exit (0); }
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. */ #include "date.h" # include<time.h> tmp * timed_1_svc(void *argp, struct svc_req *rqstp) { static tmp result; struct tm *time1; time_t t; t=time(NULL); time1=localtime(&t); result.sec=time1->tm_sec;
Exercises: 1. 2. Implement a RPC program to find the square of a given number. Implement a RPC program to