例 4-47 と 例 4-48では、クライアント作成部分が TS-RPC と TI-RPC とでどう違うかを示します。どちらのプログラムも次のことを実行します。
UDP 記述子を作成します。
遠隔ホストの RPC 結合プロセスと通信してサービスアドレスを得ます。
遠隔サービスのアドレスを記述子に結合します。
クライアントハンドルを作成してタイムアウト値を設定します。
struct hostent *h; struct sockaddr_in sin; int sock = RPC_ANYSOCK; u_short port; struct timeval wait; if ((h = gethostbyname( "host" )) == (struct hostent *) NULL) { syslog(LOG_ERR, "gethostbyname failed"); exit(1); } sin.sin_addr.s_addr = *(u_int *) hp->h_addr; if ((port = pmap_getport(&sin, PROGRAM, VERSION, "udp")) == 0) { syslog (LOG_ERR, "pmap_getport failed"); exit(1); } else sin.sin_port = htons(port); wait.tv_sec = 25; wait.tv_usec = 0; clntudp_create(&sin, PROGRAM, VERSION, wait, &sock); |
TI-RPC では、UDP トランスポートは netid udp を持つものとみなします。netid はよく知られた名前でなくてもかまいません。
struct netconfig *nconf; struct netconfig *getnetconfigent(); struct t_bind *tbind; struct timeval wait; nconf = getnetconfigent("udp"); if (nconf == (struct netconfig *) NULL) { syslog(LOG_ERR, "getnetconfigent for udp failed"); exit(1); } fd = t_open(nconf->nc_device, O_RDWR, (struct t_info *)NULL); if (fd == -1) { syslog(LOG_ERR, "t_open failed"); exit(1); } tbind = (struct t_bind *) t_alloc(fd, T_BIND, T_ADDR); if (tbind == (struct t_bind *) NULL) { syslog(LOG_ERR, "t_bind failed"); exit(1); } if (rpcb_getaddr( PROGRAM, VERSION, nconf, &tbind->addr, "host") == FALSE) { syslog(LOG_ERR, "rpcb_getaddr failed"); exit(1); } cl = clnt_tli_create(fd, nconf, &tbind->addr, PROGRAM, VERSION, 0, 0); (void) t_free((char *) tbind, T_BIND); if (cl == (CLIENT *) NULL) { syslog(LOG_ERR, "clnt_tli_create failed"); exit(1); } wait.tv_sec = 25; wait.tv_usec = 0; clnt_control(cl, CLSET_TIMEOUT, (char *) &wait); |
例 4-49 と例 4-50では、ブロードキャスト部分が旧バージョンと SunOS 5.x とでどう違うかを示します。SunOS 4.x の clnt_broadcast() は SunOS 5.x の rpc_broadcast() とほぼ同じです。大きく異なるのは、collectnames() 関数で重複アドレスを削除し、ブロードキャストに応答したホスト名を表示する点です。
statstime sw; extern int collectnames(); clnt_broadcast(RSTATPROG, RSTATVERS_TIME, RSTATPROC_STATS, xdr_void, NULL, xdr_statstime, &sw, collectnames); ... collectnames(resultsp, raddrp) char *resultsp; struct sockaddr_in *raddrp; { u_int addr; struct entry *entryp, *lim; struct hostent *hp; extern int curentry; /* 重複アドレスはカット */ addr = raddrp->sin_addr.s_addr; lim = entry + curentry; for (entryp = entry; entryp < lim; entryp++) if (addr == entryp->addr) return (0); ... /* ホスト名がわかればホスト名、わからなければアドレスを表示 */ hp = gethostbyaddr(&raddrp->sin_addr.s_addr, sizeof(u_int), AF_INET); if( hp == (struct hostent *) NULL) printf("0x%x", addr); else printf("%s", hp->h_name); } |
例 4-50 は、TI-RPC におけるブロードキャストを示します。
statstime sw; extern int collectnames(); rpc_broadcast(RSTATPROG, RSTATVERS_TIME, RSTATPROC_STATS, xdr_void, NULL, xdr_statstime, &sw, collectnames, (char *) 0); ... collectnames(resultsp, taddr, nconf) char *resultsp; struct t_bind *taddr; struct netconfig *nconf; { struct entry *entryp, *lim; struct nd_hostservlist *hs; extern int curentry; extern int netbufeq(); /* 重複アドレスはカット */ lim = entry + curentry; for (entryp = entry; entryp < lim; entryp++) if (netbufeq( &taddr->addr, entryp->addr)) return (0); ... /* ホスト名がわかればホスト名、わからなければアドレスを表示 */ if (netdir_getbyaddr( nconf, &hs, &taddr->addr ) == ND_OK) printf("%s", hs->h_hostservs->h_host); else { char *uaddr = taddr2uaddr(nconf, &taddr->addr); if (uaddr) { printf("%s¥n", uaddr); (void) free(uaddr); } else printf("unknown"); } } netbufeq(a, b) struct netbuf *a, *b; { return(a->len == b->len && !memcmp( a->buf, b->buf, a->len)); } |