この章では、トランスポートの選択およびネットワークアドレスの解決方法を示します。また、アプリケーションが使用できる通信プロトコルを指定できるようにするインタフェースについて説明します。さらに、名前からネットワークアドレスに直接マッピングする追加機能についても取り上げます。
この章では、「ネットワーク」と「トランスポート」という用語はどちらも同じ意味で使用されます。この 2 つの用語は、OSI 参照モデルのトランスポート層に準拠するプログラム可能なインタフェースを指します。「ネットワーク」という用語は、何らかの電子媒体を介して接続できる物理的なコンピュータの集まりを指す場合にも使用されます。
この章で取り上げるインタフェースはマルチスレッドに対して安全です。「マルチスレッドに対して安全」ということは、トランスポート選択機能インタフェース呼び出しを行うアプリケーションをマルチスレッド対応アプリケーション内で自由に使用できることを意味します。これらのインタフェース呼び出しは再入可能ではないので、スケーラビリティーは直線的でありません。
分散アプリケーションを各種のプロトコルに移植可能にするには、分散アプリケーションでトランスポートサービスの標準インタフェースを使用する必要があります。トランスポート選択サービスが提供するインタフェースを使用すると、アプリケーションは、使用するプロトコルを選択できます。このインタフェースによって、プロトコルと媒体に依存しないアプリケーションが実現されます。
トランスポート選択により、クライアントアプリケーションは、クライアントがサーバーとの通信を確立するまでに、どのトランスポートを使用できるかを簡単に試すことができます。トランスポート選択を使用すると、サーバーアプリケーションは複数のトランスポート上で要求を受け入れることができ、複数のプロトコルを経由して通信できます。どのトランスポートが使用できるかは、ローカルなデフォルトシーケンスで指定された順序、またはユーザーが指定した順序で試すことができます。
使用可能なトランスポートのうち、どれを選択するかを決定するのは、アプリケーションの役割です。トランスポート選択メカニズムを使用すると、選択が統一的な方法で簡単に行えます。
名前からアドレスへのマッピングを行うと、使用されるトランスポートに関係なく、アプリケーションは指定のホスト上で実行されるサービスのアドレスを取得できます。名前からアドレスへのマッピングでは、次のインタフェースを使用します。
ホスト名およびサービス名を一連のアドレスに対応づける
アドレスを、ホスト名およびサービス名に対応づける
名前からアドレスへの変換ルーチンによって割り当てられた構造体を解放する
アドレスを変換し、トランスポートに依存しないアドレスの文字表現を返す
汎用アドレスを netbuf 構造体に変換する
ブロードキャストアドレス、TCP や UDP の予約ポート機能など、トランスポート固有の機能へのインタフェースをとる
名前からアドレスにマッピングするルーチンの 1 つが失敗した理由を示すメッセージを stderr に表示する
名前からアドレスにマッピングするルーチンの 1 つが失敗した理由を示すエラーメッセージを含む文字列を返す
各ルーチンの最初の引数では、トランスポートを示す netconfig(4) 構造体を指定します。これらのルーチンは、netconfig(4) 構造体内にあるディレクトリルックアップ用のライブラリパスの配列を使用して、変換が正常終了するまで各パスを呼び出します。
表 11–1 に、名前からアドレスへのマッピング用ライブラリを示します。「名前からアドレスへのマッピングルーチンの使用」で説明しているルーチンは、netdir(3NSL) のマニュアルページに定義されています。
tcpip.so、switch.so、および nis.so というライブラリは、Solaris 環境ではすでに廃止されました。この変更の詳細は、nsswitch.conf(4) のマニュアルページおよび gethostbyname(3NSL) マニュアルページの NOTES セクションを参照してください。
ライブラリ |
トランスポートファミリ |
説明 |
---|---|---|
inet |
プロトコルファミリ inet のネットワークでは、名前からアドレスへのマッピングはファイル nsswitch.conf(4) 内にある hosts と services のエントリに基づくネームサービス切り替えによって行われる。inet 以外のファミリを使用するネットワークでは、「-」を指定すると、名前からアドレスへのマッピング機能が存在しないことを示す |
|
loopback |
ループバックトランスポートのように、文字列をアドレスとして受け入れる任意のプロトコルの、名前からアドレスにマッピングするルーチンが含まれる |
straddr.so ライブラリで使用される名前からアドレスへの変換ファイルは、システム管理者が作成します。システム管理者はまた、このような変換ファイルを保守します。straddr.so ファイルには、/etc/net/transport-name/hosts と /etc/net/transport-name/services があります。transport-name は、文字列アドレ スを受け入れるトランスポートのローカル名であり、/etc/netconfig ファイルの network ID フィールドに指定されています。たとえば、ticlts のホストファイルは、/etc/net/ticlts/hosts となり、ticlts のサービスファイルは、/etc/net/ticlts/services となります。
ほとんどの文字列アドレスは「ホスト」と「サービス」を区別しません。しかし、文字列をホスト部分とサービス部分とに分けると、ほかのトランスポートとの間で一貫性が保たれます。/etc/net/transport-name/hosts ファイルには、次のようにホストアドレスと見なされるテキスト文字列に続いて、ホスト名を定義します。
joyluck
carpediem
thehop
pongo
ループバックトランスポートは自分が含まれているホスト以外では実行できないため、ほかのホストを記述しても意味がありません。
/etc/net/transport-name/services には、サービス名に続いて、サービスアドレスを特定する文字列を定義します。
rpcbind rpc listen serve |
ルーチンは、ホストアドレス、ピリオド (. )、およびサービスアドレスを結合して完全な文字列アドレスを作成します。たとえば、pongo での listen サービスのアドレスは、pongoaddr.serve になります。
このライブラリを使用するトランスポート上で、あるアプリケーションが特定のホスト上のサービスアドレスを要求するとき、ホスト名が /etc/net/transport/hosts に定義されていなければなりません。また、サービス名も /etc/net/transport/services に定義されていなければなりません。どちらか一方でも欠けると、名前からアドレスへの変換が失敗します。
この節では、使用できるマッピングルーチンについて簡単に説明します。ルーチンは、ネットワーク名を返すか、または対応するネットワークアドレスにネットワーク名を変換します。netdir_getbyname(3NSL)、netdir_getbyaddr(3NSL)、および taddr2uaddr(3NSL) はデータへのポインタを返しますが、これらのポインタは netdir_free(3NSL) 呼び出しで解放する必要があります。
int netdir_getbyname(struct netconfig *nconf, struct nd_hostserv *service, struct nd_addrlist **addrs);
netdir_getbyname(3NSL) は service に指定されたホスト名とサービス名を、nconf で指定されたトランスポートに一致するアドレスセットに対応づけます。nd_hostserv と nd_addrlist の各構造体は、netdir(3NSL) のマニュアルページに定義されています。アドレスへのポインタは、addrs に返されます。
使用可能なすべてのトランスポート上で、ホストおよびサービスのすべてのアドレスを取得するには、getnetpath(3NSL) または getnetconfig(3NSL) のいずれかで返される各 netconfig(4) 構造体を使用して netdir_getbyname(3NSL) を呼び出します。
int netdir_getbyaddr(struct netconfig *nconf, struct nd_hostservlist **service, struct netbuf *netaddr);
netdir_getbyaddr(3NSL) は、アドレスをホスト名とサービス名に対応づけます。このインタフェースは、netaddr に指定されたアドレスを使用して呼び出され、ホスト名とサービス名のペアのリストを service に返します。nd_hostservlist 構造体は、netdir(3NSL) に定義されています。
void netdir_free(void *ptr, int struct_type);
netdir_free(3NSL) ルーチンは、名前からアドレスへの変換ルーチンによって割り当てられた構造体を解放します。次の表に、パラメータに使用できる値を示します。
表 11–2 netdir_free(3NSL) ルーチン
struct_type |
ptr |
---|---|
ND_HOSTSERV |
nd_hostserv 構造体へのポインタ |
ND_HOSTSERVLIST |
nd_hostservlist 構造体へのポインタ |
ND_ADDR |
netbuf 構造体へのポインタ |
ND_ADDRLIST |
nd_addrlist 構造体へのポインタ |
char *taddr2uaddr(struct netconfig *nconf, struct netbuf *addr);
taddr2uaddr(3NSL) は、addr が指すアドレスを変換し、アドレスのトランスポートに依存しない文字列表現を返します。この文字列表現のことを「汎用アドレス」と呼びます。nconf には、アドレスが有効なトランスポートを指定します。汎用アドレスは、free(3C) で解放できます。
struct netbuf *uaddr2taddr(struct netconfig *nconf, char *uaddr);
uaddr が指す汎用アドレスは、netbuf 構造体に変換されます。nconf には、アドレスが有効なトランスポートを指定します。
int netdir_options(const struct netconfig *config, const int option, const int fildes, char *point_to_args);
netdir_options(3NSL) は、ブロードキャストアドレス、TCP や UDP の予約ポート機能など、トランスポート固有の機能へのインタフェースを提供します。nconf にはトランスポートを指定し、option にはトランスポート固有の動作を指定します。fd の値は option の値によって指定するかどうかが決まります。4 つ目の引数は、操作固有のデータを指します。
次の表に、option に使用できる値を示します。
表 11–3 netdir_options に指定できる値
オプション |
説明 |
---|---|
ND_SET_BROADCAST |
ブロードキャスト用のトランスポートを設定する (トランスポートがブロードキャスト機能をサポートしている場合) |
ND_SET_RESERVEDPORT |
アプリケーションが予約ポートにバインドできるようにする (トランスポートがそのようなバインドを許可している場合) |
ND_CHECK_RESERVEDPORT |
アドレスが予約ポートに対応しているかどうかを検証する (トランスポートが予約ポートをサポートしている場合) |
ND_MERGEADDR |
ローカルに意味のあるアドレスを、クライアントホストが接続できるアドレスに変換する |
netdir_perror(3NSL) ルーチンは、名前からアドレスにマッピングするルーチンの 1 つが失敗した理由を示すメッセージを stderr に表示します。
void netdir_perror(char *s);
netdir_sperror(3NSL) ルーチンは、名前からアドレスにマッピングするルーチンの 1 つが失敗した理由を示すエラーメッセージを含む文字列を返します。
char *netdir_sperror(void);
次の例に、ネットワーク選択および名前からアドレスへのマッピングを示します。
#include <netconfig.h> #include <netdir.h> #include <sys/tiuser.h> struct nd_hostserv nd_hostserv; /* host and service information */ struct nd_addrlist *nd_addrlistp; /* addresses for the service */ struct netbuf *netbufp; /* the address of the service */ struct netconfig *nconf; /* transport information*/ int i; /* the number of addresses */ char *uaddr; /* service universal address */ void *handlep; /* a handle into network selection */ /* * Set the host structure to reference the "date" * service on host "gandalf" */ nd_hostserv.h_host = "gandalf"; nd_hostserv.h_serv = "date"; /* * Initialize the network selection mechanism. */ if ((handlep = setnetpath()) == (void *)NULL) { nc_perror(argv[0]); exit(1); } /* * Loop through the transport providers. */ while ((nconf = getnetpath(handlep)) != (struct netconfig *)NULL) { /* * Print out the information associated with the * transport provider described in the "netconfig" * structure. */ printf("Transport provider name: %s\n", nconf->nc_netid); printf("Transport protocol family: %s\n", nconf->nc_protofmly); printf("The transport device file: %s\n", nconf->nc_device); printf("Transport provider semantics: "); switch (nconf->nc_semantics) { case NC_TPI_COTS: printf("virtual circuit\n"); break; case NC_TPI_COTS_ORD: printf("virtual circuit with orderly release\n"); break; case NC_TPI_CLTS: printf("datagram\n"); break; } /* * Get the address for service "date" on the host * named "gandalf" over the transport provider * specified in the netconfig structure. */ if (netdir_getbyname(nconf, &nd_hostserv, &nd_addrlistp) != ND_OK) { printf("Cannot determine address for service\n"); netdir_perror(argv[0]); continue; } printf("<%d> addresses of date service on gandalf:\n", nd_addrlistp->n_cnt); /* * Print out all addresses for service "date" on * host "gandalf" on current transport provider. */ netbufp = nd_addrlistp->n_addrs; for (i = 0; i < nd_addrlistp->n_cnt; i++, netbufp++) { uaddr = taddr2uaddr(nconf,netbufp); printf("%s\n",uaddr); free(uaddr); } netdir_free( nd_addrlistp, ND_ADDRLIST ); } endnetconfig(handlep);