RPC のブロードキャストが要求されると、メッセージはネットワーク上の rpcbind デーモンに送られます。要求されたサービスが登録されている rpcbind デーモンは、その要求をサーバーに送ります。ブロードキャスト RPC と通常の RPC 呼び出しとの主な相違点を次に示します。
通常の RPC では応答は 1 つですが、ブロードキャスト RPC には複数の応答があります (メッセージに応答するすべてのマシンから応答が返されます)。
ブロードキャスト RPC は、UDP のようにブロードキャスト RPC をサポートする非接続型プロトコルでしか使用できません。
ブロードキャスト RPC では、正常終了以外の応答は返されません。したがって、ブロードキャスタと遠隔のサービスでバージョンの不一致があれば、サービスからブロードキャスタには何も返されません。
ブロードキャスト RPC では、rpcbind で登録されたデータグラムサービスだけがアクセス可能です。サービスアドレスはホストごとに異なりますので、rpc_broadcast() は、rpcbind のネットワークアドレスにメッセージを送信します。
ブロードキャスト要求のサイズはローカルネットワークの最大伝送ユニット (MTU:maximum trasfer unit) により制限されます。イーサネットの MTU は 1500 バイトです。
例 4-21 では、rpc_broadcast() の使用方法を示し、引数を説明します。
/* * bcast.c: RPC ブロードキャストの使用例 */ #include <stdio.h> #include <rpc/rpc.h> main(argc, argv) int argc; char *argv[]; { enum clnt_stat rpc_stat; rpcprog_t prognum; rpcvers_t vers; struct rpcent *re; if(argc != 3) { fprintf(stderr, "usage : %s RPC_PROG VERSION¥n", argv[0]); exit(1); } if (isdigit( *argv[1])) prognum = atoi(argv[1]); else { re = getrpcbyname(argv[1]); if (! re) { fprintf(stderr, "Unknown RPC service %s¥n", argv[1]); exit(1); } prognum = re->r_number; } vers = atoi(argv[2]); rpc_stat = rpc_broadcast(prognum, vers, NULLPROC, xdr_void, (char *)NULL, xdr_void, (char *)NULL, bcast_proc, NULL); if ((rpc_stat != RPC_SUCCESS) && (rpc_stat != RPC_TIMEDOUT)) { fprintf(stderr, "broadcast failed: %s¥n", clnt_sperrno(rpc_stat)); exit(1); } exit(0); } |
例 4-22 の関数 bcast_proc() では、ブロードキャストに対する応答を収集します。通常は、最初の応答だけを取り出すか、応答をすべて収集します。bcast_proc() は、応答を返したサーバーの IP アドレスを表示します。この関数は FALSE を返して応答の収集を続け、RPC クライアントコードはタイムアウトになるまでブロードキャストを再送信し続けます。
bool_t bcast_proc(res, t_addr, nconf) void *res; /* 応答なし */ struct t_bind *t_addr; /* 応答したアドレス */ struct netconfig *nconf; { register struct hostent *hp; char *naddr; naddr = taddr2naddr(nconf, &taddr->addr); if (naddr == (char *) NULL) { fprintf(stderr,"Responded: unknown¥n"); } else { fprintf(stderr,"Responded: %s¥n", naddr); free(naddr); } return(FALSE); } |
TRUE が返されるとブロードキャストは終了し、rpc_broadcast() は正常終了します。FALSE が返された場合は、次の応答を待ちます。数秒間待ってから、要求が再びブロードキャストされます。応答が返されない場合は、rpc_broadcast() は RPC_TIMEDOUT を返します。