250 likes | 377 Views
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 - rpegen header file add_xdr.c - rpcgen data representation file
E N D
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 - rpegen header file • add_xdr.c - rpcgen data representation file • add_clnt.c - rpcgen client stub code • add_svc.c - rpcgen remote procedures • addClient.c - client application code • addServer.c - remote procedure code • client_intfce.c - interface code between app and rpcgen code CS423
Add addClient.c Client_intfce.c add_clnt.c compile Client.exe add.h rpcgen add.x add _xdr.c compile Server.exe add _svc.c addServer.c CS423
Add (add.x interface specification) program ADDSERV { version ADDVERS { intaddFunc(structnumtype) = 1; void myshutdown(void) = 2; } = 1; } =9876; structnumtype { int int1; int int2; int int3; }; CS423
Add (program file linkages) add_svc.c addClient.c RPC addServer.c add_clnt.c add_xdr.c add.h CS423
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 <stdlib.h> #include <stdio.h> #include <unistd.h> #include <rpc/rpc.h> #include "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; CS423
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, structsvc_req *data) { printf ("Shutting down server....\n"); exit (0); } CS423
Add (program file linkages) add_svc.c RPC addClient.c addServer.c add_clnt.c add_xdr.c add.h CS423
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 CS423
Add.h(RPCgen) #if defined(__STDC__) || defined(__cplusplus) #define addfunc 1 extern int * addfunc_1(structnumtype *, CLIENT *); extern int * addfunc_1_svc(structnumtype *, structsvc_req *); #define myshutdown 2 extern void * myshutdown_1(void *, CLIENT *); extern void * myshutdown_1_svc(void *, structsvc_req *); extern int addserv_1_freeresult (SVCXPRT *, xdrproc_t, caddr_t); /* the xdr functions */ extern bool_txdr_numtype (XDR *, numtype*); #endif CS423
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;} CS423
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); } CS423
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);} CS423
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 *); CS423
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; } CS423
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; } CS423
Add (add_svc.c) int main (intargc, 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); } CS423
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 */ } CS423
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> CS423
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 CS423