ONC+ 開発ガイド

接続型トランスポート

例 4–20 に示すサンプルプログラムは、あるホストのファイルを別のホストにコピーするプログラムです。RPC の send() 呼び出しで標準入力から読み込まれたデータがサーバー receive() に送信され、サーバーの標準出力に書き出されます。また、このプログラムでは、1 つの XDR ルーチンでシリアライズとデシリアライズの両方を実行する方法も示します。ここでは、接続型トランスポートを使用します。


例 4–20 リモートコピー (両方向 XDR ルーチン)

/*
 * XDR ルーチン:
 *      復号化時にネットワークを読み取り fp に書き込む
 *      符号化時に fp を読み取りネットワークに書き込む
 */
#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)                 /* 解放するものなし */
		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);
 	}
	}
}

例 4–21例 4–22 には、例 4–20 に示した xdr_rcp()ルーチンだけでシリアライズとデシリアライズを行うプログラムを示します。


例 4–21 リモートコピー : クライアント側ルーチン

/* 送信側のルーチン */
#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);
}
 

次に、受信側のルーチンを定義します。サーバー側では、xdr_rcp() がすべての処理を自動的に実行することに注意してください。


例 4–22 リモートコピー : サーバー側ルーチン

/*
 * 受信側ルーチン
 */
#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();                    /* この関数は戻らない */
	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();
 }
 
}