remote procedure call - york university · cosc3213 m. aboelaze yu fall 2002 rpc • the procedure...
TRANSCRIPT
COSC3213 M. Aboelaze
YUFall 2002
RPC
• The procedure is running on a different machine than the calling program
1. The server registers its services (procedures) with the portmapper.
2. The client contacts the portmapper to determine if the requested service (procedure) is available; and if so, on which port.
3. The client contacts the server to initiate service.
COSC3213 M. Aboelaze
YUFall 2002
RPC
• Network communication is hidden by procedure calls.
• Procedures may be executed on different hosts.
• The RPC mechanism hides the details. • A programmer decides which procedures are
executed, and where (on which hosts). • To make the details transparent, a remote
procedure call should be as much like a local call as possible.
COSC3213 M. Aboelaze
YUFall 2002
RPC
• Some issues we have to address– Data representation (could be different on the
2 machines).– Reliability (at most one, at least one, exact
one).– RPC uses at least once if it receives a reply, and
zero or more if no reply– XDR eXternal Data Representation is used as a
standard way to represent data when you send it to another machine
COSC3213 M. Aboelaze
YUFall 2002
RPC
• XDR specifies data formats for most of the data types clients and server exchange
• Examples are int (32 bit integer), unsigned int, hyper (64 bit signed binary number), float (32 bits), double (64 bits), string, fixed array, and structure.
• XDR allows the programmer to compose aggregate types from other types.
COSC3213 M. Aboelaze
YUFall 2002
RPC
• Implicit Types– XDR specifies the encoding of the data, but
does not support any information to specify its type.
– For example, int is encoded as big-endian with 32 bits, but no indication that this 32 bits are an int
– Client and server must agree on the exact format of the message they exchange
COSC3213 M. Aboelaze
YUFall 2002
RPC• Software support• Routines for conversion• Programmer creates an
XDR streams and appends data to it
• TO create a stream• Then append to it an int• Examples xdr_u_int,
xdr_short, xdr_float
#include <rpc/xdr.h>#define BUFFSIZE 4000
XDR *xdrs /*pointer to XDR stream*/
Char buf[MAXSIZE]
Xdrmem_create(xdrs, buf, BUFSIZE, XDR_ENCODE);
Thenint i;i=260;
xdr_int(xdrs, &i);
COSC3213 M. Aboelaze
YUFall 2002
Example
• Example on a dictionary program• First, a regular program is written
and tested• Once the program is tested, we can
change it into an RPC type.
COSC3213 M. Aboelaze
YUFall 2002
Example (regular program)/* dict.c - main, initw, nextin, insertw, deletew, lookupw */
#include <stdlib.h>#include <stdio.h>#include <ctype.h>#include <string.h>
#define MAXWORD 50 /* maximum length of a command or word */#define DICTSIZ 100 /* maximum number of entries in diction.*/char dict[DICTSIZ][MAXWORD+1];/*storage for a dictionary of words*/int nwords = 0; /* number of words in the dictionary */
int nextin(char *cmd, char *word), initw(), insertw(const char *word), deletew(const char *word), lookupw(const char *word);
/*--------------------------------------------------------------* main - insert, delete, or lookup words in a dictionary as
specified*-----------------------------------------------------------------*/
COSC3213 M. Aboelaze
YUFall 2002
Example (regular program)Int main(int argc, char argv[])
{char word[MAXWORD+1]; /* space to hold word from input line*/char cmd;int wrdlen; /* length of input word */
while (1) {wrdlen = nextin(&cmd, word);if (wrdlen < 0)
exit(0);switch (cmd) {case 'I': /* "initialize" */
initw();printf("Dictionary initialized to empty.\n");break;
case 'i': /* "insert" */insertw(word);printf("%s inserted.\n",word);break;
case 'd': /* "delete" */if (deletew(word))
printf("%s deleted.\n",word);else
printf("%s not found.\n",word);break;
COSC3213 M. Aboelaze
YUFall 2002
Example (regular program)case 'l': /* "lookup" */
if (lookupw(word))printf("%s was found.\n",word);
elseprintf("%s was not found.\n",word);
break;case 'q': /* quit */
printf("program quits.\n");exit(0);
default: /* illegal input */printf("command %c invalid.\n", cmd);break;
}}
}
COSC3213 M. Aboelaze
YUFall 2002
Example (regular program)/*-------------------------------------------------------------------
* nextin - read a command and (possibly) a word from the next input line*-------------------------------------------------------*/
int nextin(char *cmd, char *word){
int i, ch;
ch = getc(stdin);while (isspace(ch)) ch = getc(stdin);if (ch == EOF) return -1;*cmd = (char) ch; ch = getc(stdin);while (isspace(ch)) ch = getc(stdin);if (ch == EOF) return -1;if (ch == '\n') return 0;i = 0;while (!isspace(ch)) {
if (++i > MAXWORD) {printf("error: word too long.\n");exit(1);
}*word++ = ch;ch = getc(stdin);
}*word=‘\0’; return i;
}
COSC3213 M. Aboelaze
YUFall 2002
Example (regular program)/*------------------------------------------------------------------------
* initw - initialize the dictionary to contain no words at all*------------------------------------------------------------------------*/
intinitw(){
nwords = 0;return 1;
}
/*------------------------------------------------------------------------* insertw - insert a word in the dictionary*------------------------------------------------------------------------*/
intinsertw(const char *word){
strcpy(dict[nwords], word);nwords++;return nwords;
}
COSC3213 M. Aboelaze
YUFall 2002
Example (regular program)/*------------------------------------------------------------------------
* deletew - delete a word from the dictionary*------------------------------------------------------------------*/
int deletew(const char *word){
int i;
for (i=0 ; i<nwords ; i++)if (strcmp(word, dict[i]) == 0) {
nwords--;strcpy(dict[i], dict[nwords]);return 1;
}return 0;
}/*------------------------------------------------------------------------* lookupw - look up a word in the dictionary*------------------------------------------------------------------------*/
int lookupw(const char *word){
int i;
for (i=0 ; i<nwords ; i++)if (strcmp(word, dict[i]) == 0)
return 1;return 0;
}
COSC3213 M. Aboelaze
YUFall 2002
Dividing the program into local and remote procedures
• Moving one or more procedure to a remote machine require some changes.
• On the client side, we need some code to marshal the arguments and translate them into a machine-independent representation (XDR), and translate back the returned results to the machine rep.
• We also need some code on the procedure side to translate XDR machine XDR
COSC3213 M. Aboelaze
YUFall 2002
Dividing the program into local and remote procedures
• This is implemented as 2 stub procedures
Program 1
Client stub
Server stub
Procedure ARPC CALL
Machine A Machine B
COSC3213 M. Aboelaze
YUFall 2002
Dividing the program into local and remote procedures
• The previous case was for a very simple program with only one remote procedure.
• In general, we can have more than one procedure running on a remote machine.
• The remote program consists of a single server process that must be running before any call to it.
• An RPC must specify the address of the machine, and the name of the procedure running on this machine.
• The server program consists of a dispatcher and the procedures.
• The dispatcher send the call to the intended procedure.
COSC3213 M. Aboelaze
YUFall 2002
Dividing the program into local and remote procedures
• One way to make the transition from a single conventional program to a distributed one is to use the same name of the procedures for the stub procedure on the caller machine
• Program A calls procedure B in a conventional program.
• If we names the stub procedure on the client side B, and it has the same interface as the procedure B, we may even run the program without recompiling A (just link it with the stub named B).
COSC3213 M. Aboelaze
YUFall 2002
Rpcgen
• rpcgen reads an input file contains a specification of a remote program.
• It generates four output files, each contain source code.
• If the input file is Q.x, the output files are as follows
COSC3213 M. Aboelaze
YUFall 2002
Rpcgen• File Name• Q.h
• Q-xdr.c
• Q_clnt.c
• Q_scv.c
• Contents• Decleration of constants used
for both client and server• XDR procedure calls to
marshal arguments
• Client side communication stub
• Server side communication stub
COSC3213 M. Aboelaze
YUFall 2002
Client application
Q.x rpcgen
Q_clnt.c
Q.h
Q_xdr.c
Q_svc.c
C compiler
C compiler
Client
Server
Remote procedures
COSC3213 M. Aboelaze
YUFall 2002
Eight Steps to Distributed Application
1. Build and test a conventional application2. Divide the program by choosing a set of procedures to move to a
remote machine3. Write an rpcgen specification for the remote program, including
names and numbers for the remote procedures and the declaration of their arguments.
4. Run the rpcgen to check the specifications (will generate 4 files).5. Write stub interface for client and server (application program
and 3 files generated by rpcgen)6. Compile and link together the client program (remote procedures
and 3 files generated by rpcgen)7. Compile and link together the server program8. Start the server on the remote machine and then client on local
COSC3213 M. Aboelaze
YUFall 2002
Step 1
• Build and test a conventional algorithm
• Done in the previous slides.
COSC3213 M. Aboelaze
YUFall 2002
Step 2
• Divide the program into a set of procedures to be executed on a remote machine
• The original program
main
nextin
insertw
initw
deletew
lookupw
COSC3213 M. Aboelaze
YUFall 2002
Step 2
• Division of the dictionary programComputer 1 Computer 2
main nextin
insertw
initw deletew
lookupwData structure used by the program
COSC3213 M. Aboelaze
YUFall 2002
Step 2 (dict1.c)/* dict1.c - main, nextin */
#include <stdio.h>#include <ctype.h>
#define MAXWORD 50 /* maximum length of a command or word */
/*------------------------------------------------------------------------* main - insert, delete, or lookup words in a dictionary as specified*------------------------------------------------------------------------*/
intmain(argc, argv)int argc;char *argv[];{
char word[MAXWORD+1]; /* space to hold word from input line */char cmd;int wrdlen; /* length of input word*/
COSC3213 M. Aboelaze
YUFall 2002
Step 2 (dict1.c)while (1) {
wrdlen = nextin(&cmd, word);if (wrdlen < 0)
exit(0);switch (cmd) {case 'I': /* "initialize" */
initw();printf("Dictionary initialized to empty.\n");break;
case 'i': /* "insert" */insertw(word);printf("%s inserted.\n",word);break;
case 'd': /* "delete" */if (deletew(word))
printf("%s deleted.\n",word);else
printf("%s not found.\n",word);break;
COSC3213 M. Aboelaze
YUFall 2002
step 2 (dict1.c)case 'l': /* "lookup" */
if (lookupw(word))printf("%s was found.\n",word);
elseprintf("%s was not found.\n",word);
break;case 'q': /* quit */
printf("program quits.\n");exit(0);
default: /* illegal input */printf("command %c invalid.\n", cmd);break;
}}
}
COSC3213 M. Aboelaze
YUFall 2002
Step 2 (dict1.c)/*------------------------------------------------------------------------
* nextin - read a command and (possibly) a word from the next input line*------------------------------------------------------------------------*/
int nextin(cmd, word)char *cmd, *word;{
int i, ch;
ch = getc(stdin);while (isspace(ch)) ch = getc(stdin);if (ch == EOF) return -1;*cmd = (char) ch; ch = getc(stdin);while (isspace(ch)) ch = getc(stdin);if (ch == EOF) return -1;if (ch == '\n') return 0;i = 0;while (!isspace(ch)) {
if (++i > MAXWORD) {printf("error: word too long.\n"); exit(1);
}*word++ = ch; ch = getc(stdin);
}*word=‘\0’; return i;
}
COSC3213 M. Aboelaze
YUFall 2002
Step 2 (dict2.c)/* dict2.c - initw, insertw, deletew, lookupw */
#define MAXWORD 50 /* maximum length of a command or word */#define DICTSIZ 100 /* maximum number of entries in diction.*/char dict[DICTSIZ][MAXWORD+1];/* storage for a dictionary of words */int nwords = 0; /* number of words in the dictionary */
/*------------------------------------------------------------------------* initw - initialize the dictionary to contain no words at all*------------------------------------------------------------------------*/
intinitw(){
nwords = 0;return 1;
}
COSC3213 M. Aboelaze
YUFall 2002
Step 2 (dict2.c)/*------------------------------------------------------------------------
* insertw - insert a word in the dictionary ------------------------------------------------------------------------ */
int insertw(word)char *word;{
strcpy(dict[nwords], word);nwords++;return nwords;
}/*------------------------------------------------------------------------
* deletew - delete a word from the dictionary*------------------------------------------------------------- */
int deletew(word)char *word;{
int i;
for (i=0 ; i<nwords ; i++)if (strcmp(word, dict[i]) == 0) {
nwords--;strcpy(dict[i], dict[nwords]);return 1;
}return 0;
}
COSC3213 M. Aboelaze
YUFall 2002
Step 2 (dict2.c)/*---------------------------------------------------------------------
* lookupw - look up a word in the dictionary*------------------------------------------------------------------*/
intlookupw(word)char *word;{
int i;
for (i=0 ; i<nwords ; i++)if (strcmp(word, dict[i]) == 0)
return 1;return 0;
}
COSC3213 M. Aboelaze
YUFall 2002
Step 2
• Note that MAXWORD appears in both programs.
• Also, the data structure used to store the words is declared only in dict2.c since it is used only there, dict12.c doesn’t know anything about it
• You may want to check by compiling both programs
cc –c dict1.c cc –c dict2.c
COSC3213 M. Aboelaze
YUFall 2002
Step 3• The rpcgen specification file contains constants, type
definition, and declaration for the client and server program.
• All specifications must be given in the RPC programming language, which is similar to C (string instead of *char).
• The program only define these constants and types shared between client and server.
• The specification file uses upper case names for procedures and programs.
• The names become symbolic references which could be used in a C program.
COSC3213 M. Aboelaze
YUFall 2002
Step 3 (rdict.x)/* rdict.x */
/* RPC declarations for dictionary program */
const MAXWORD = 50; /* maximum length of a command or word */const DICTSIZ = 100; /* number of entries in dictionary */
struct example { /* unused structure declared here to */int exfield1; /* illustrate how rpcgen builds XDR */char exfield2; /* routines to convert structures. */
};/*------------------------------------------------------------------------* RDICTPROG - remote program that provides insert, delete, and lookup*------------------------------------------------------------------------*/
program RDICTPROG { /* name of remote program (not used) */version RDICTVERS { /* declaration of version (see below) */
int INITW(void) = 1;/* first procedure in this program */int INSERTW(string) = 2;/* second procedure in this program */int DELETEW(string) = 3;/* third procedure in this program */int LOOKUPW(string) = 4;/* fourth procedure in this program */
} = 1; /* definition of the program version */} = 0x30090949; /* remote program number (must be */
/* unique) */
COSC3213 M. Aboelaze
YUFall 2002
Step 4
• After the specification has been completed, run the rpcgen program
rpcgen rdixt.x• Rpcgen uses the name of the input
file to generate the output files.• 5 output files are generatedrdict.h rdict_clnt.c rdict_svc.c, rdixt_xdr.c
COSC3213 M. Aboelaze
YUFall 2002
Step 3 (rdict.h)#define RDICTPROG 0x30090949
#define RDICTVERS 1#define INITW 1extern int * initw_1();#define INSERTW 2extern int * insertw_1();#define DELETEW 3extern int * deletew_1();#define LOOKUPW 4extern int * lookupw_1();extern int rdictprog_1_freeresult();
/* the xdr functions */extern bool_t xdr_example();
#endif /*!_RDICT_H_RPCGEN */
/** Please do not edit this file. It was generated using rpcgen.*/#ifndef _RDICT_H_RPCGEN#define _RDICT_H_RPCGEN
#include <rpc/rpc.h>#define MAXWORD 50#define DICTSIZ 100
struct example {int exfield1;char exfield2;
};typedef struct example example;
COSC3213 M. Aboelaze
YUFall 2002
Step 3 (rdict.h explained)
• The declared procedures comprisethe interface version of the server-side stub.
• Procedures names having been generated by taking the declared procedure names, mapping them to lower case, and appending underscore followed by the program number.
• Thus, allowing rpcgen to choose its own naming convention, while allowing the original called procedure not to change
COSC3213 M. Aboelaze
YUFall 2002
The XDR File/*
* Please do not edit this file.* It was generated using rpcgen.*/
#include "rdict.h"
bool_t xdr_example(xdrs, objp)register XDR *xdrs;example *objp;
{
#if defined(_LP64) || defined(_KERNEL)register int *buf;
#elseregister long *buf;
#endif
if (!xdr_int(xdrs, &objp->exfield1))return (FALSE);
if (!xdr_char(xdrs, &objp->exfield2))return (FALSE);
return (TRUE);}
COSC3213 M. Aboelaze
YUFall 2002
The XDR File• In our example, the only declared type is a
structure with one integer filed and one character filed.
• rdict_xdr.c contains the code needed to convert a structure of type example from the native representation to the external data representation.
• If one of the remote procedures did use the an example structure, rpcgen would generate code in both client and server to call xdr_example to convert the representation.