例 4–13 に、対応するサーバー側プログラム svcudp_create() を示します。サーバー側では svc_tli_create() を使用します。
svc_tli_create() は、アプリケーションで次のように詳細な制御を行う必要があるときに使用します。
送信バッファと受信バッファのサイズを指定します。引数 fd は、渡された時に結合されていないことがあります。その場合、fd は指定されたアドレスに結合され、そのアドレスがハンドルに格納されます。結合されたアドレスが NULL に設定されていて、fd が最初から結合されていない場合、任意の最適なアドレスへ結合されます。
サービスを rpcbind により登録するには、rpcb_set() を使用します。
#include <stdio.h>
#include <rpc/rpc.h>
#include <netconfig.h>
#include <netinet/in.h>
SVCXPRT *
svcudp_create(fd)
register int fd;
{
struct netconfig *nconf;
SVCXPRT *svc;
int madefd = FALSE;
int port;
void *handlep;
struct t_info tinfo;
/* どのトランスポートも使用不可の場合 */
if ((handlep = setnetconfig() ) == (void *) NULL) {
nc_perror("server");
return((SVCXPRT *) NULL);
}
/*
* 非接続型で、プロトコルファミリが INET、名前が UDP の
* トランスポートが見つかるまで探す。
*/
while (nconf = getnetconfig( handlep)) {
if ((nconf->nc_semantics == NC_TPI_CLTS) &&
(strcmp( nconf->nc_protofmly, NC_INET) == 0 )&&
(strcmp( nconf->nc_proto, NC_UDP) == 0 ))
break;
}
if (nconf == (struct netconfig *) NULL) {
endnetconfig(handlep);
return((SVCXPRT *) NULL);
}
if (fd == RPC_ANYFD) {
fd = t_open(nconf->nc_device, O_RDWR, &tinfo);
if (fd == -1) {
(void) endnetconfig();
return((SVCXPRT *) NULL);
}
madefd = TRUE;
} else
t_getinfo(fd, &tinfo);
svc = svc_tli_create(fd, nconf, (struct t_bind *) NULL,
tinfo.tsdu, tinfo.tsdu);
(void) endnetconfig(handlep);
if (svc == (SVCXPRT *) NULL) {
if (madefd)
(void) t_close(fd);
return((SVCXPRT *)NULL);
}
return (svc);
}
|
この例では、clntudp_create() と同じ方法でネットワーク選択を行なっています。svc_tli_create() で結合しているため、ファイル記述子は明示的にはトランスポートアドレスと結合されません。
svcudp_create() はオープンしている fd を使用できます。有効なファイル記述子が渡されなければ、選択された netconfig 構造体を使用してこのルーチン内でオープンします。