DOC HOME SITE MAP MAN PAGES GNU INFO SEARCH PRINT BOOK
 
Programming with Remote Procedure Calls (RPC)

An example of a remote copy program using connection-oriented transports

This is an example that copies a file from one system to another. The initiator of the RPC send call takes its standard input and sends it to the server receive, which prints it on standard output. This also illustrates an XDR procedure that behaves differently on serialization than on deserialization.

   /*
    * The xdr routine:     on decode, read from wire, write onto fp
    *                      on encode, read from fp, write onto wire
    */
   #include <stdio.h>
   #include <rpc/rpc.h>
   

xdr_rcp(xdrs, fp) XDR *xdrs; FILE *fp; { unsigned long size; char buf[BUFSIZ], *p;

if (xdrs->x_op == XDR_FREE)/* nothing to free */ return 1; while (1) { if (xdrs->x_op == XDR_ENCODE) { if ((size = fread(buf, sizeof(char), BUFSIZ, fp)) == 0 && ferror(fp)) { fprintf(stderr, "can't fread\n"); return (1); } } p = buf; if (!xdr_bytes(xdrs, &p, &size, BUFSIZ)) return 0; if (size == 0) return 1; if (xdrs->x_op == XDR_DECODE) { if (fwrite(buf, sizeof(char), size, fp) != size) { fprintf(stderr, "can't fwrite\n"); return (1); } } } }

Note that in the following two screens, the serializing and deserializing is done only by xdr_bytes.
   /* The sender routines */
   

#include <stdio.h> #include <netdb.h> #include <rpc/rpc.h> #include <sys/socket.h> #include <sys/time.h>

main(argc, argv) int argc; char **argv; { int xdr_rcp();

if (argc < 2) { fprintf(stderr, "usage: %s servername\n", argv[0]); exit(1); } if (callcots(argv[1], RCPPROG, RCPPROC, RCPVERS, xdr_rcp, stdin, xdr_void, 0) != 0) { exit(1); } exit(0); }

callcots(host, prognum, procnum, versnum, inproc, in, outproc, out) char *host, *in, *out; xdrproc_t inproc, outproc; { enum clnt_stat clnt_stat; register CLIENT *client; struct timeval total_timeout;

if ((client = clnt_create(host, prognum, versnum, "circuit_v")) == NULL) { perror("clnt_create"); return (-1); } total_timeout.tv_sec = 20; total_timeout.tv_usec = 0; clnt_stat = clnt_call(client, procnum, inproc, in, outproc, out, total_timeout); clnt_destroy(client); if (clnt_stat != RPC_SUCCESS) { clnt_perror("callcots"); } return ((int)clnt_stat); }

   /*
    * The receiving routines
    */
   #include <stdio.h>
   #include <rpc/rpc.h>
   

main () { int rcp_service(), xdr_rcp();

if (svc_create(rpc_service, RCPPROG, RCPVERS, "circuit_v") == 0) { fprintf("svc_create: error\n"); exit(1); } svc_run(); /* never returns */ fprintf(stderr, "svc_run should never return\n"); }

rcp_service(rqstp, transp) register struct svc_req *rqstp; register SVCXPRT *transp; { switch (rqstp->rq_proc) { case NULLPROC: if (svc_sendreply(transp, xdr_void, 0) == 0) { fprintf(stderr, "err: rcp_service"); return (1); } return; case RCPPROC: if (!svc_getargs(transp, xdr_rcp, stdout)) { svcerr_decode(transp); return (1); } if (!svc_sendreply(transp, xdr_void, 0)) { fprintf(stderr, "can't reply\n"); return (1); } return (0); default: svcerr_noproc(transp); return (1); } }

Note that on the server side no explicit action was taken after receiving the arguments. This is because xdr_rcp did all the necessary dirty work automatically.
© 2004 The SCO Group, Inc. All rights reserved.
UnixWare 7 Release 7.1.4 - 27 April 2004