Connection-Oriented Transports
Example 4-20 copies a file from one host to another.
The RPC send() call reads standard input and sends the
data to the server receive(), which writes the data to
standard output. This example also illustrates an XDR procedure that behaves
differently on serialization and on deserialization. A connection-oriented
transport is used.
Example 4-20 Remote Copy (Two-Way XDR Routine)
/*
* The xdr routine:
* on decode, read wire, write to fp
* on encode, read fp, write to wire
*/
#include <stdio.h>
#include <rpc/rpc.h>
bool_t
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(TRUE);
while (TRUE) {
if (xdrs->x_op == XDR_ENCODE) {
if ((size = fread( buf, sizeof( char ), BUFSIZ, fp))
== 0 && ferror(fp)) {
fprintf(stderr, "can't fread\n");
return(FALSE);
} else
return(TRUE);
}
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(FALSE);
} else
return(TRUE);
}
}
}
|
In Example 4-21 and Example 4-22,
the serializing and deserializing are done only by the xdr_rcp()
routine shown in Example 4-20.
Example 4-21 Remote Copy Client Routines
/* The sender routines */
#include <stdio.h>
#include <netdb.h>
#include <rpc/rpc.h>
#include <sys/socket.h>
#include <sys/time.h>
#include "rcp.h"
main(argc, argv)
int argc;
char **argv;
{
int xdr_rcp();
if (argc != 2 7) {
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")
== (CLIENT *) NULL)) {
clnt_pcreateerror("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 following code example defines the receiving routines. Note that
in the server, xdr_rcp() did all the work automatically.
Example 4-22 Remote Copy Server Routines
/*
* The receiving routines
*/
#include <stdio.h>
#include <rpc/rpc.h
#include "rcp.h"
main()
{
void rcp_service();
if (svc_create(rpc_service,RCPPROG,RCPVERS,"circuit_v") == 0) {
fprintf(stderr, "svc_create: errpr\n");
exit(1);
}
svc_run(); /* never returns */
fprintf(stderr, "svc_run should never return\n");
}
void
rcp_service(rqstp, transp)
register struct svc_req *rqstp;
register SVCXPRT *transp;
{
switch(rqstp->rq_proc) {
case NULLPROC:
if (svc_sendreply(transp, xdr_void, (caddr_t) NULL) == FALSE)
fprintf(stderr, "err: rcp_service");
return;
case RCPPROC:
if (!svc_getargs( transp, xdr_rcp, stdout)) {
svcerr_decode(transp);
return();
}
if(!svc_sendreply(transp, xdr_void, (caddr_t) NULL)) {
fprintf(stderr, "can't reply\n");
return();
}
return();
default:
svcerr_noproc(transp);
return();
}
}
|