0% found this document useful (0 votes)
134 views

Remote Procedure Call

Remote procedure call (RPC) allows a program to execute a subroutine on another computer over a network without explicitly coding the network details. RPC works like a function call, with arguments passed to the remote procedure and a response returned. The client makes a request that is sent to and processed by the server, with the client blocked until a reply is received. To develop an RPC application, the communication protocol must be defined, then client and server programs and stubs generated from the protocol definition. The client calls remote procedures by passing data, and receives returned data.
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
134 views

Remote Procedure Call

Remote procedure call (RPC) allows a program to execute a subroutine on another computer over a network without explicitly coding the network details. RPC works like a function call, with arguments passed to the remote procedure and a response returned. The client makes a request that is sent to and processed by the server, with the client blocked until a reply is received. To develop an RPC application, the communication protocol must be defined, then client and server programs and stubs generated from the protocol definition. The client calls remote procedures by passing data, and receives returned data.
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
You are on page 1/ 15

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.

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.

RPC Application Development


The RPC alternative is to Establish an server on the remote machine that can respond to queries. Retrieve information by calling a query, which will be quicker than previous approach.

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. The communication protocol is achieved by generated stubs and these stubs and rpc (and other libraries) will need to be linked in.

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. For the protocol you must identify the name of the service procedures, and data types of parameters and return arguments. The protocol compiler reads a definition and automatically generates client and server stubs. uses its own language (RPC language or RPCL) which looks very similar to preprocessor directives.
rpcgen rpcgen

exists as a standalone executable compiler that reads special files denoted by a .x prefix.

So to compile a RPCL file you simply do

rpcgen rpcprog.x

This will generate possibly four files:


rpcprog_clnt.c -- the client stub rpcprog_svc.c -- the server stub rpcprog_xdr.c -- If necessary XDR (external data representation) rpcprog.h

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.

Defining Client and Server Application Code


We must now write the client and application code. They must communicate via procedures and data types specified in the Protocol. 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 application calls the remote procedure, 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. We will briefly discuss these below before expanding the most common of these in later chapters. Create a file named rand.x with the following context:

/* 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:

Makefile.rand, rand.h, rand_server.c, rand_client.c, rand_clnt.c, rand_svc.c

The programs rand_client.c and rand_server.c are the client and server programs that need to be edited to accomplish the goals.

The original source code of rand_server.c

/*

* 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; }

The original source code of rand_client.c


/* * 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 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 }

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); }

The modified source code of rand_client.c

/* * 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); }

The modified source code of rand_client.c


/* * 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); }

The modified source code of rand_server.c Modify the rand_server.c as follows.


#include "rand.h" #include <stdlib.h> double * get_next_random_1_svc(void *argp, struct svc_req *rqstp) { static double result; result = ((double)(rand()%1000000))*0.000001; return &result; }

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.

The server part:

The client part:

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;

result.min=time1->tm_min; result.hour=time1->tm_hour; /* * insert server code here */ return &result; }

Exercises: 1. 2. Implement a RPC program to find the square of a given number. Implement a RPC program to

You might also like