Remote Procedure Call

The goal of remote procedure call is to make the invocation of a procedure on a remote machine appear as though it were local.

The local procedure calls a stub which marshalls the paramaters and packs the call into a message to the remote machine.

On the remote machine there is another stub which unpacks the parameters and calls a local procedure to do the work. This passes the reults back to the stub which packs the result back up and sends it back over the network to the originating stub, which upnacks the result and returns it to the original calling procedure.

Sun provides tools that build the stubs automatically. The following example shows their use.

The files are here.

The Header File

This file contains the information that the two ends need to know in order to match the called process.


/*  date.x */

/*
* Define 2 procedures:
*     bin_date_l() returns the binary time and date (no arguments)
*     str_datel() takes a binary time and returns a human readable string
*/


program DATE_PROG {
   version DATE VERS {
     long    BIN_DATE(void) = 1;    /* procedure number */
     string  STR_DATE(long) = 2;     /* procedure number */
  } = 1;                              /* version number  */
} = 0x31234567;                       /* program number  */

If you compile this with rpcgen you get date.h Which looks like this.

#define DATE_PROG   ((u_log)0x31234567)
#define DATE_VERS   ((u_long)1)
#define BIN_DATE     ((u_long)1)
extern long         *bin_date_1();
#define STR_DATE    ((u long)2)
extern char         **str_date_1();

You should NEVER edit this file directly. rpcgen also makes two other files

  1. one called date_svc.c which contains the server stub.
  2. one called date_clnt.c which contains the client stub.

The programmer needs to write the server procedures.

The Server procedures

In this case these are in a file date_proc.c

/*
* dateproc.c - remote proceduies; called by server stub.
*/

#include          /* standard RPC include file */
#include      "date.h"       /* this file is generated by rpcgen */

/*
* Return the binary date and time.
*/

long *
bin_date_1()
{     static long    timeval; /* must be static */
      long           time();     /*   Unix function  */

    timeval = time((long *) 0);
     return(&timeval);
}
/*
* Convert a binary time and return a human readable
*/
char **
str_date_1(bintime)
long   *bintime;
{
     static char    *ptr;          /* must be sttic */
     char           *ctime();      /* Unix function */

     ptr = ctime(bintime);         /* convert to local time */
      
     return(&ptr);        /* return the address of pointer */
}





The Client Procedure

The client procedure is contained in rdate.c

/* 
* rdate.c - client program for remote date service
*/

#include      
#include          /* standard RPC include file  */
#include      "date.h"       /* this file is generated by rpcgen */

main(argc, argv)
int    argc;
char   *argv [];
{
       CLIENT       *cl;           /* RPC handle  */
       char         *server;
       long         *lresult;      /* return Value from bin_date() */
       char         **sresult;     /* return value form str_date() */

       if (argc != 2){
              fprintf(stderr, "usage: ~s hostname\n", argv[0]);
              exit(1);
       }

        server= argv[1];
       /*
       * Create the client "handle."
       */

       if ( (cl = clnt_create(server, DATE_PROG, DATE_VERS, "udp")) == NULL) {
              /*
               * Couldn't establish  Connection with server.
               */


              clnt_pcreateerror(server):
              exit(2);
       }

/*
*  First call the remote procedure "bin_date"
*/
 if ( (lresult = bin_date_1(NULL, cl)) == NULL) {
     clnt_perror(cl, server) ;
      exit(3);
  }
 printf("time on host %s =  %ld\n", server, *lresult);
 /* Now call the remote procedure "str date"*/
 if ( (sresult = str_date_1(lresult, cl)) == NULL) {
      clnt_perror(cl, server);
      exit(4);
  }

 printf("time on host %s = %s", server, *sresult);

clnt_destroy(cl); /* done with the handle */
exit(0);
}

Getting it all together.

To generate the server type

gcc -o date_svc date_proc.c date_svc.c -lnsl 

To generate the client

gcc -o rdate rdate.c date_clnt.c  -lnsl 

You then run the server in the background on one machine, (eg hollerith). You run the client by typing: rdate hollerith at another machine.


Last Change: 31 March 1997

Return to Networks home page [GO HOME] Return to Systems Programming Home Page