390 likes | 507 Views
Linux RPC. Comer Chapter 21 (RPCgen Concept) RFC 1057 – RPC Spec. UNIX Network Programming - Stevens. Using Remote Procedure Calls. As a program specification technique For program specification and as an abstraction during design Explicitly in the implementation
E N D
Linux RPC Comer Chapter 21 (RPCgen Concept) RFC 1057 – RPC Spec. UNIX Network Programming - Stevens
Using Remote Procedure Calls • As a program specification technique • For program specification and as an abstraction during design • Explicitly in the implementation • For design and implementation, from scratch • For design and implementation, with standard libraries • For automated implementation
RPC Programming MechanismsONC (Open Network Computing) • XDR library routines for data conversion • XDR library routines for complex data structures • RPC run-time library routines • Program generator tool
RPC Programming Process • Dividing the program into local and remote procedures. RPC Proc A Server Stub Client Stub Proc B
RPC Dispatching(Procedure Location) RPC Proc A2 Dispatcher Proc A1 RPC Server Stub Server Stub Client Stub Client Stub Proc B1 Proc B2
RPC Interface Specification Proc A Server Comm RPC Client Iface Server Iface Client comm Proc B
RPCgen Input and Output • Input • Q.x Interface specification file • Output • Q.h Declarations header file • Q_xdr.cpp XDR procedure calls used to marshal arguments • Q_clnt.cpp Client-side communications stub • Q_svc.cpp Server-side communications stub
RPC Process Flow Client application Client interface Q_clnt.cpp compile Client Q.h rpcgen Q.x Q_xdr.cpp compile Server Q_svc.cpp Remote procedures Server interface
RPC General Build Procedure Develop Interface Develop Client Develop Server
Developing the Interface MyApp.x RPCgen MyApp_clnt.c Client Stub MyApp.h MyApp_svc.c Server Stub MyApp_xdr.c
Developing the Server MyApp.x RPCgen MySrvr.c MyApp_xdr.c MyApp.h C Compiler MyApp_svc.c Server Stub Linker MySrvr.exe
Developing the Client MyApp.idl RPCgen MyClnt.c MyApp_xdr.c MyApp.h C Compiler MyApp_clnt.c Client Stub Linker MyClnt.exe
How the Server Prepares for a Connection • (Be certain that Portmap is running) • Create UDP service • Register UDP service with Portmap • Create TCP service • Register TCP service with Portmap • Run service... • Uses select( ) to monitor ports.
Start Portmap Portmap is included in all Linux distributions as a standard server. Under Red Hat Fedora Open services applet ,select portmap and start From command line (as root) /sbin/services portmap start Other distributions should be similar
Server concurrency mode RPC servers can be created in either single threaded or multi-threaded mode. Servers automatically create and (when done) destroy a thread for each incoming connection.
Register the Server Program svc_register(port#, SERV#, VER#, serv_func, proto#); port#: port on which the service is active SERV#: unique number for the service VER#: version for this particular service serv_func: name by which this function is called proto#: IPPROTO_UDP or IPPROTO_TCP
How the Client Establishes a Connection • Make a Remote Procedure Call • Find the Server Host Computer • Find Server Process Port # (through Portmap) • Create a (connection) to the Server Process
How the Client Establishes a Connection clnt_create(server, SERV#, VER#, proto#); remote procedure call... Clnt_destroy(CLIENT);
Example #1 • Temperature Server (Fahrenheit to Centigrade) • Parameters passed as integers • TCP / IP port connection • Source files: • temp.x • Tclient.c • tempServer.c
temp.x program TEMPSERV { version TEMPVERS { intTempConv(int) = 1; //procedure number } = 1; //version number } = 77; //program number
TClient.c #include <stdio.h>, <stdlib.h>, <string.h> #include <rpc/rpc.h> #include "temp.h" #define YES 0 #define NO 1 void main (int argc, char *argv[]) { int tempconvert(int temp, char *srvr); int temperature, nuTemp; int loopFlag; char srvr[25]; CLIENT * cl;
TClient.c (cont) strcpy (srvr, argv[1]); cl = clnt_create(srvr, TEMPSERV, TEMPVERS, "tcp"); loopFlag = YES; while(loopFlag == YES) { printf("Enter temperature in Faherenheit (-999 to quit)"); scanf ("%d", &temperature); ans = tempconv_1(&temperature, cl);
TClient.c (cont) if (ans != NULL) nuTemp = * ans; if (temperature == -999 || temperature == -9999) { loopFlag = NO; printf ("Goodbye...\n"); continue; } printf("That’s %2d in centigrade\n", nuTemp); } clnt_destroy(cl); return 0; }
tempServer.c #include <stdlib.h>, <unistd.h>, <stdio.h> #include <rpc/rpc.h>, "temp.h" static int count; static int nuTemp; int *tempconv_1_svc (int *val, struct svc_req * rqst) { int oldTemp; oldTemp = *val;
tempServer.c if (oldTemp == -9999) { printf("We're shutting down...\n"); exit (0); } printf("We got a temperature of %d, ", oldTemp); count++; nuTemp = (int)((5*(oldTemp -32)) / 9.0); printf("and we returned a value of %d\n", nuTemp); sleep(1); return (&nuTemp); }
Files created with rpcgen • Input: • temp.x • Output • temp.h • temp_xdr.c (NULL file) • temp_clnt.c • temp_svc.c
temp.h #include <rpc/rpc.h> #ifdef __cplusplus extern "C" { #endif #define TEMPSERV 77 #define TEMPVERS 1 #if defined(__STDC__) || defined(__cplusplus) #define TempConv 1 extern int * tempconv_1(int *, CLIENT *); extern int * tempconv_1_svc(int *, structsvc_req *); extern int tempserv_1_freeresult (SVCXPRT *, xdrproc_t, caddr_t); #ifdef __cplusplus} #endif #endif /* !_TEMP_H_RPCGEN */
temp_xdr.c #include <rpc/rpc.h> #include "temp.h"
temp_clnt.c #include <memory.h> /* for memset */ #include "temp.h“ /* Default timeout can be changed using clnt_control() */ static structtimeval TIMEOUT = { 25, 0 }; int *tempconv_1(int *argp, CLIENT *clnt){ static intclnt_res; memset((char *)&clnt_res, 0, sizeof(clnt_res));
temp_clnt.c (cont) if (clnt_call (clnt, TempConv, (xdrproc_t) xdr_int, (caddr_t) argp, (xdrproc_t) xdr_int, (caddr_t) &clnt_res, TIMEOUT) != RPC_SUCCESS) { return (NULL); } return (&clnt_res);}
temp_svc.c #include "temp.h“ #include <stdio.h> #include <stdlib.h> #include <rpc/pmap_clnt.h> #include <string.h> #include <memory.h> #include <sys/socket.h> #include <netinet/in.h> #ifndef SIG_PF #define SIG_PF void(*)(int) #endif
temp_svc.c (cont) static void tempserv_1(structsvc_req *rqstp, register SVCXPRT *transp){ union { int tempconv_1_arg; } argument; char *result; xdrproc_t _xdr_argument, _xdr_result; char *(*local)(char *, structsvc_req *); switch (rqstp->rq_proc) { case NULLPROC: (void) svc_sendreply (transp, (xdrproc_t) xdr_void, (char *)NULL); return; case TempConv: _xdr_argument = (xdrproc_t) xdr_int; _xdr_result = (xdrproc_t) xdr_int; local = (char *(*)(char *, structsvc_req *)) tempconv_1_svc; break; default: svcerr_noproc (transp); return; }
temp_svc.c (cont) 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; }
temp_svc.c (cont) int main (intargc, char **argv){ register SVCXPRT *transp; pmap_unset (TEMPSERV, TEMPVERS); transp = svcudp_create(RPC_ANYSOCK); if (transp == NULL) { fprintf (stderr, "%s", "can’t create udp service."); exit(1); } if (!svc_register(transp, TEMPSERV, TEMPVERS, tempserv_1, IPPROTO_UDP)) { fprintf (stderr, "%s", "unable to register (TEMPSERV, TEMPVERS, udp)."); exit(1); }
temp_svc.c (cont) transp = svctcp_create(RPC_ANYSOCK, 0, 0); if (transp == NULL) { fprintf (stderr, "%s", "cannot create tcp service."); exit(1); } if (!svc_register(transp, TEMPSERV, TEMPVERS, tempserv_1, IPPROTO_TCP)) { fprintf (stderr, "%s", "unable to register (TEMPSERV, TEMPVERS, tcp)."); exit(1); } svc_run (); fprintf (stderr, "%s", "svc_run returned"); exit (1); /* NOTREACHED */}
Sample Client Output D:\data\RPC\onrpc_temp\client\Debug>client localhost Enter the temperature in Faherenheit (-999 to quit)32 That would be 0 in centigrade Enter the temperature in Faherenheit (-999 to quit)100 That would be 37 in centigrade Enter the temperature in Faherenheit (-999 to quit)212 That would be 100 in centigrade Enter the temperature in Faherenheit (-999 to quit)-9999 Goodbye... D:\data\RPC\onrpc_temp\client\Debug>
Sample Server Output D:\data\RPC\examples\onrpc_temp\server\Debug>server We got a temperature of 32, and we returned a value of 0 We got a temperature of 100, and we returned a value of 37 We got a temperature of 212, and we returned a value of 100 We're shutting down... D:\data\RPC\examples\onrpc_temp\server\Debug>
Summary • Linux RPC Implementation models SUN ONCRPC functionality • RPC specific programming limited to linking original applications code with rpcgen interface code.