The following is an example using the rcp process. This example includes an eXternal Data Representation (XDR) procedure that behaves differently on serialization than on deserialization. The initiator of the Remote Procedure Call (RPC) snd call takes its standard input and sends it to the rcv process on the server, which prints the data to standard output. The snd call uses Transmission Control Protocol (TCP).
/* * 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); } } } }
/* * 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(); int err; if (argc < 2) { fprintf(stderr, "usage: %s servername\n", argv[0]); exit(-1); } if ((err = callrpctcp(argv[1], RCPPROG, RCPPROC, RCPVERS, xdr_rcp, stdin, xdr_void, 0) != 0)) { clnt_perrno(err); fprintf(stderr, "can't make RPC call\n"); exit(1); } exit(0); }
callrpctcp(host, prognum, procnum, versnum, inproc, in, outproc, out) char *host, *in, *out; xdrproc_t inproc, outproc;
{ struct sockaddr_in server_addr; int socket = RPC_ANYSOCK; enum clnt_stat clnt_stat; struct hostent *hp; register CLIENT *client; struct timeval total_timeout;
if ((hp = gethostbyname(host)) == NULL) { fprintf(stderr, "can't get addr for '%s'\n", host); return (-1); } bcopy(hp->h_addr, (caddr_t)&server_addr.sin_addr, hp->h_length); server_addr.sin_family = AF_INET; server_addr.sin_port = 0; if ((client = clnttcp_create(&server_addr, prognum, versnum, &socket, BUFSIZ, BUFSIZ)) == NULL) { perror("rpctcp_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); return (int)clnt_stat; }
/* * The receiving routines */ #include <stdio.h> #include <rpc/rpc.h>
main() { register SVCXPRT *transp; int rcp_service(), xdr_rcp();
if ((transp = svctcp_create(RPC_ANYSOCK, BUFSIZ, BUFSIZ)) == NULL) { fprintf("svctcp_create: error\n"); exit(1); } pmap_unset(RCPPROG, RCPVERS); if (!svc_register(transp, RCPPROG, RCPVERS, rcp_service, IPPROTO_TCP)) { fprintf(stderr, "svc_register: 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_FP: if (!svc_getargs(transp, xdr_rcp, stdout)) { svcerr_decode(transp); return; } if (!svc_sendreply(transp, xdr_void, 0)) { fprintf(stderr, "can't reply\n"); return; } return (0); default: svcerr_noproc(transp); return; } }