例 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));
}
|