Transcript RPC Part 3

RPC Part 3
More Linux RPC
Add RPC program
Objectives:
• Pass multiple arguments from calling program to remote
procedure
• Support multiple procedures within a single interface
• Files:
– add.x - interface definition
•
•
•
•
add.h
add_xdr.c
add_clnt.c
add_svc.c
- rpegen header file
- rpcgen data representation file
- rpcgen client stub code
- rpcgen remote procedures
– addClient.c - client application code
– addServer.c - remote procedure code
– client_intfce.c - interface code between app and rpcgen code
UMKC - CSTP
CS423
2
Add
addClient.c
Client_intfce.c
add_clnt.c
add.h
add.x
compile
Client.exe
compile
Server.exe
rpcgen
add _xdr.c
add _svc.c
addServer.c
UMKC - CSTP
CS423
3
Add (add.x interface specification)
program ADDSERV {
version ADDVERS {
int addFunc(struct numtype) = 1;
void myshutdown(void) = 2;
} = 1;
} = 9876;
struct numtype
{
int int1;
int int2;
int int3;
};
UMKC - CSTP
CS423
4
Add (program file linkages)
addClient.c
add_svc.c
RPC
addServer.c
add_clnt.c
add_xdr.c
UMKC - CSTP
add.h
CS423
5
Add (addClient.c) 1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <rpc/rpc.h>
#include "add.h"
#define YES 0
#define NO 1
char srvr[25];
void myshutdown ();
int addfunc (int num1, int num2, int num3);
int main (int argc, char *argv[])
{
int num1, num2, num3, result;
int loopFlag;
char ans, dummy;
Add (addClient.c) 2
if (argc != 2)
{
fprintf(stderr, "usage: %s host\n", argv[0]);
exit (1);
}
strcpy (srvr, argv[1]);
loopFlag = YES;
while(loopFlag == YES)
{
printf("Enter 3 numbers to add ");
scanf ("%d%d%d%c", &num1, &num2, &num3, &dummy);
result = addfunc (num1, num2, num3);
printf ("The sum of those numbers is %d\n", result);
Add (addClient.c) 3
printf ("Do you want to do another calculation (y or n)? ");
scanf ("%c%c", &ans, &dummy);
if (ans != 'y' && ans != 'Y')
{
loopFlag = NO;
printf ("Goodbye...\n");
if (ans == 'Z')
{
myshutdown ();
}
continue;
}// end-of-if
}//end-of-while
return 0;
}
Add (addClient.c) 4
int addfunc (int num1, int num2, int num3)
{
CLIENT *cl;
int *result;
struct numtype nums;
cl = clnt_create(srvr, ADDSERV, ADDVERS, "tcp");
if (cl == NULL)
{
printf("Couldn't create client\n");
exit (1);
}
nums.int1 = num1;
nums.int2 = num2;
nums.int3 = num3;
result = addfunc_1(&nums, cl);
clnt_destroy(cl);
return (*result);
}
Add (addClient.c) 5
void myshutdown ()
{
CLIENT *cl;
void *dummy;
cl = clnt_create(srvr, ADDSERV, ADDVERS, "tcp");
if (cl == NULL)
{
printf("Couldn't create client\n");
exit (1);
}
myshutdown_1(dummy, cl);
clnt_destroy(cl);
}
Add (addServer.c)
#include
#include
#include
#include
#include
<stdlib.h>
<stdio.h>
<unistd.h>
<rpc/rpc.h>
"add.h"
static int sum;
int *addfunc_1_svc (numtype *nums, struct svc_req *data){
int nuint1, nuint2, nuint3;
nuint1 = nums->int1;
nuint2 = nums->int2;
nuint3 = nums->int3;
UMKC - CSTP
CS423
11
Add (addServer.c)
printf("We got numbers %d, %d, and %d. ",nuint1,nuint2,nuint3);
sum = nuint1 + nuint2 + nuint3;
printf("and the sum is %d\n", sum);
sleep(1);
return (&sum);
}
void *myshutdown_1_svc (void *dummy, struct svc_req *data)
{
printf ("Shutting down server....\n");
exit (0);
}
UMKC - CSTP
CS423
12
Add (program file linkages)
addClient.c
add_svc.c
RPC
addServer.c
add_clnt.c
add_xdr.c
UMKC - CSTP
add.h
CS423
13
Add.h (RPCgen)
#ifndef _ADD_H_RPCGEN
#define _ADD_H_RPCGEN
#include <rpc/rpc.h>
extern "C" {
struct numtype
{
int int1;
int int2;
int int3;
};typedef struct numtype numtype;
#define ADDSERV 9876
#define ADDVERS 1
UMKC - CSTP
CS423
14
Add.h (RPCgen)
#if defined(__STDC__) || defined(__cplusplus)
#define addfunc 1
extern int * addfunc_1(struct numtype *, CLIENT *);
extern int * addfunc_1_svc(struct numtype *, struct svc_req *);
#define myshutdown 2
extern void * myshutdown_1(void *, CLIENT *);
extern void * myshutdown_1_svc(void *, struct svc_req *);
extern int addserv_1_freeresult (SVCXPRT *, xdrproc_t, caddr_t);
/* the xdr functions */
extern bool_t xdr_numtype (XDR *, numtype*);
#endif
UMKC - CSTP
CS423
15
Add (add_xdr.c)
#include "add.h“
bool_t xdr_numtype (XDR *xdrs, numtype *objp)
{
register int32_t *buf;
if (!xdr_int (xdrs, &objp->int1))
return FALSE;
if (!xdr_int (xdrs, &objp->int2))
return FALSE;
if (!xdr_int (xdrs, &objp->int3))
return FALSE;
return TRUE;}
UMKC - CSTP
CS423
16
Add (add_clnt.c)
#include <memory.h>
#include "add.h“
/* Default timeout can be changed using clnt_control() */
static struct timeval TIMEOUT = { 25, 0 };
int *addfunc_1(struct numtype *argp, CLIENT *clnt)
{
static int clnt_res;
memset((char *)&clnt_res, 0, sizeof(clnt_res));
if (clnt_call (clnt, addfunc,
(xdrproc_t) xdr_numtype, (caddr_t) argp,
(xdrproc_t) xdr_int, (caddr_t) &clnt_res,
TIMEOUT) != RPC_SUCCESS)
{
return (NULL);
}
return (&clnt_res);
}
UMKC - CSTP
CS423
17
Add (add_clnt.c)
void *myshutdown_1(void *argp, CLIENT *clnt)
{
static char clnt_res;
memset((char *)&clnt_res, 0, sizeof(clnt_res));
if (clnt_call (clnt, myshutdown,
(xdrproc_t) xdr_void, (caddr_t) argp,
(xdrproc_t) xdr_void, (caddr_t) &clnt_res,
TIMEOUT) != RPC_SUCCESS)
{
return (NULL);
}
return ((void *)&clnt_res);}
UMKC - CSTP
CS423
18
Add (add_svc.c)
#include "add.h“ <stdio.h> <stdlib.h> <rpc/pmap_clnt.h>
#include <string.h> <memory.h> <sys/socket.h> <netinet/in.h>
#ifndef SIG_PF
#define SIG_PF void(*)(int)
#endif
static void
addserv_1(struct svc_req *rqstp, register SVCXPRT *transp)
{
union {
struct numtype addfunc_1_arg;
} argument;
char *result;
xdrproc_t _xdr_argument, _xdr_result;
char *(*local)(char *, struct svc_req *);
UMKC - CSTP
CS423
19
Add (add_svc.c)
switch (rqstp->rq_proc) {
case NULLPROC:
svc_sendreply (transp, (xdrproc_t) xdr_void, (char *)NULL);
return;
case addfunc:
_xdr_argument = (xdrproc_t) xdr_numtype;
_xdr_result = (xdrproc_t) xdr_int;
local = (char *(*)(char *, struct svc_req *)) addfunc_1_svc;
break;
case myshutdown:
_xdr_argument = (xdrproc_t) xdr_void;
_xdr_result = (xdrproc_t) xdr_void;
local= (char *(*)(char *,struct svc_req *))myshutdown_1_svc;
break;
default:
svcerr_noproc (transp);
return;
}
UMKC - CSTP
CS423
20
Add (add_svc.c)
memset ((char *)&argument, 0, sizeof (argument));
if (!svc_getargs (transp, (xdrproc_t) _xdr_argument, (caddr_t) &argument))
{
svcerr_decode (transp);
return;
}
result = (*local)((char *)&argument, rqstp);
if (result != NULL && !svc_sendreply(transp, (xdrproc_t) _xdr_result,
result)) {
svcerr_systemerr (transp);
}
if (!svc_freeargs (transp, (xdrproc_t) _xdr_argument, (caddr_t) &argument))
{
fprintf (stderr, "%s", "unable to free arguments");
exit (1);
}
return;
}
UMKC - CSTP
CS423
21
Add (add_svc.c)
int main (int argc, char **argv)
{
register SVCXPRT *transp;
pmap_unset (ADDSERV, ADDVERS);
transp = svcudp_create(RPC_ANYSOCK);
if (transp == NULL)
{
fprintf (stderr, "%s", "cannot create udp service.");
exit(1);
}
if (!svc_register(transp, ADDSERV, ADDVERS, addserv_1, IPPROTO_UDP))
{
fprintf (stderr,"%s", "unable to register(ADDSERV, ADDVERS, udp)");
exit(1);
}
UMKC - CSTP
CS423
22
Add (add_svc.c)
transp = svctcp_create(RPC_ANYSOCK, 0, 0);
if (transp == NULL)
{
fprintf (stderr, "%s", "cannot create tcp service.");
exit(1);
}
if (!svc_register(transp, ADDSERV, ADDVERS, addserv_1, IPPROTO_TCP))
{
fprintf (stderr, "%s","unable to register (ADDSERV,ADDVERS,tcp)");
exit(1);
}
svc_run ();
fprintf (stderr, "%s", "svc_run returned");
exit (1);
/* NOTREACHED */
}
UMKC - CSTP
CS423
23
Add results
D:\data\RPC\examples\add2>client localhost
Enter 3 numbers to add 123 09 8765
The sum of those numbers is 8897
Do you want to do another calculation (y or n)? Z
Goodbye...
D:\data\RPC\examples\add2>
D:\data\RPC\examples\add2>server
We got numbers 123, 9, and 8765. and the sum is 8897
Shutting down server....
D:\data\RPC\examples\add2>
UMKC - CSTP
CS423
24
Summary
• The objective of RPC (including ONCRPC) is to provide a
way to access remote procedures in a way that does not
require knowledge of inter-machine communications.
• ONCRPC supports the core capabilities of SUN ONC RPC
• ONCRPC uses sockets as the underlying platform for
supporting RPC
• ONCRPC supports:
– Multiple interfaces on a single machine
– Multiple versions of a single interface
– Multiple functions (remote procedures) within a single interface
UMKC - CSTP
CS423
25