|
|
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.