The changes in client creation from TS-RPC to TI-RPC are illustrated in Example 4-42 and Example 4-43. Each example
Creates a UDP descriptor.
Contacts the remote host's RPC binding process to get the services address.
Binds the remote service's address to the descriptor.
Creates the client handle and set its time out.
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_long *) 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);
The TI-RPC version assumes that the UDP transport has the netid udp. A netid is not necessarily a well-known name.
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);
Example 4-44 and Example 4-45show the differences between broadcast in TS-RPC and TI-RPC. The older clnt_broadcast() is similar to the newer rpc_broadcast(). The primary difference is in the collectnames() function: deletes duplicate addresses and displays the names of hosts that reply to the broadcast.
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_long addr; struct entry *entryp, *lim; struct hostent *hp; extern int curentry; /* weed out duplicates */ addr = raddrp->sin_addr.s_addr; lim = entry + curentry; for (entryp = entry; entryp < lim; entryp++) if (addr == entryp->addr) return (0); ... /* print the host's name (if possible) or address */ hp = gethostbyaddr(&raddrp->sin_addr.s_addr, sizeof(u_long), AF_INET); if( hp == (struct hostent *) NULL) printf("0x%x", addr); else printf("%s", hp->h_name); }
Example 4-45 shows the Broadcast for 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(); /* weed out duplicates */ lim = entry + curentry; for (entryp = entry; entryp < lim; entryp++) if (netbufeq( &taddr->addr, entryp->addr)) return (0); ... /* print the host's name (if possible) or address */ 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)); }