250 likes | 382 Vues
This project focuses on creating an RPC (Remote Procedure Call) system in Linux, allowing a client to pass multiple arguments to remote procedures and supporting multiple procedures within a single interface. Key components include defining interfaces and procedures, generating client and server code using rpcgen, and implementing functionalities to perform computations on received parameters. The provided files include the interface definitions, header files, data representation, and client/server logic for invoking RPC methods and handling results.
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