ネットワークインタフェース

サーバー

サーバーの例においても接続要求待機を行うためにトランスポートエンドポイントを確立する必要があります。 例 3-4 では定義とローカル管理を行うステップを例で示しています。


例 3-4 オープンおよびバインドのサーバー実装

#include <tiuser.h>
#include <stropts.h>
#include <fcntl.h>
#include <stdio.h>
#include <signal.h>

#define DISCONNECT -1
#define SRV_ADDR 1								/* サーバーのアドレス*/
int conn_fd;			/* ここで接続の確立*/
extern int t_errno;

main()
{
   int listen_fd;							/* トランスポートエンドポイント待機*/
   struct t_bind *bind;
   struct t_call *call;

   if ((listen_fd = t_open("/dev/exmp", O_RDWR,
      (struct t_info *) NULL)) == -1) {
      t_error("t_open failed for listen_fd");
      exit(1);
   }
   if ((bind = (struct t_bind *)t_alloc( listen_fd, T_BIND, T_ALL))
         == (struct t_bind *) NULL) {
      t_error("t_alloc of t_bind structure failed");
      exit(2);
   }
   bind->qlen = 1;

   /*
    * プロバイダのアドレスの形式を推測するため
    * このプログラムはトランスポートに依存する
    */
    bind->addr.len = sizeof(int);
   *(int *) bind->addr.buf = SRV_ADDR;
   if (t_bind (listen_fd, bind, bind) < 0 ) {
      t_error("t_bind failed for listen_fd");
      exit(3);
   }

   #if (!defined(_XOPEN_SOURCE) ||(_XOPEN_SOURCE_EXTENDED -0 != 1))
   /*
    * 正しいアドレスがバインドされているかどうか
    *
    * XTI の場合このテストは不要
    */

   if (bind->addr.len != sizeof(int) ||
      *(int *)bind->addr.buf != SRV_ADDR) {
      fprintf(stderr, "t_bind bound wrong address¥n");
      exit(4);
    }
    #endif

クライアント同様、サーバーはまず選択したトランスポートプロバイダとトランスポートエンドポイントを確立するため t_open(3NSL) を呼び出します。エンドポイント listen_fd は接続要求待機を行うために使用されます。

次にサーバーはアドレスをエンドポイントへバインドします。アドレスは各クライアントがサーバーへアクセスする際に使用されます。2 つ目の引数はエンドポイントへバインドするアドレスを指定する t_bind 構造体を指します。t_bind 構造体は以下の形式です。

struct t_bind {
 	struct netbuf addr;
 	unsigned qlen;
}

addr はバインドされたアドレスを示し、qlen は未処理の接続要求の最大件数を指定します。すべての XTI 構造および定数定義は xti.h を介しアプリケーションプログラムで使用可能になります。すべての TLI 構造体および定数定義は tiuser.h に格納されます。

アドレスは以下の形式で netbuf 構造体で指定されます。

struct netbuf {
 	unsigned int maxlen;
 	unsigned int len;
 	char *buf;
}

maxlen はバッファーの最大長をバイト単位で指定、len はバッファー内のデータのバイト長を指定、そして buf はデータを格納しているバッファーを指します。

t_bind 構造体では、データはトランスポートアドレスを識別します。qlen は待機可能な接続要求の最大数を指定します。qlen の値が正の場合、エンドポイントを接続要求の待機に使用することが可能となります。t_bind(3NSL) は、ただちにバイトされたアドレスに各接続要求の待機を行うようトランスポートプロバイダに指示します。サーバーは 1 つずつ接続要求の待機を解除し、受け付けまたは拒否を行う必要があります。次の接続要求を受信する前に 1 つの接続要求の処理および応答を行うサーバーの場合、qlen の値は 1 が適切です。応答を行う前に複数の接続要求の待機を解除するサーバーの場合は、より長い待ち行列を指定する必要があります。この例のサーバーでは、一度に 1 つの接続要求の処理しか行わないため、qlen1 に設定してあります。

t_alloc(3NSL)t_bind 構造体を割り当てるために呼び出されます。t_alloc(3NSL) には 3 つの引数があります。トランスポートエンドポイントのファイル記述子、割り当てる構造体の識別子、そして割り当てる netbuf バッファーを指定するフラグです ( netbuf バッファーを使用する場合)。T_ALL はすべての netbuf バッファーの割り当てを指定し、この例では addr バッファーが割り当てられる要因となります。バッファーのサイズは自動的に決定され、maxlen に格納されます。

各トランスポートプロバイダは個別にアドレス空間を管理します。トランスポートプロバイダには複数のトランスポートエンドポイントに同じトランスポートアドレスをバインドするものと、各エンドポイントに固有のアドレスをバインドするものがあります。XTI と TLI のアドレスバインド方法には大きく異なる部分があります。

TLI のルールでは、プロバイダが要求されたアドレスのバインドが可能かを判定します。バインドが行えない場合、そのアドレス空間で別の有効アドレスを捜しトランスポートエンドポイントにバインドします。アプリケーションプログラムは、バインドされたアドレスが事前にクライアントに通知されたものと同一であることをチェックする必要があります。XTI ではプロバイダが要求されたアドレスのバインドを行えないと判定した場合、t_bind(3NSL) をエラーで終了します。

t_bind(3NSL) が成功した場合、プロバイダは接続要求の待機を開始し、通信の次のフェーズに移ります。