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

付録 A UNIX ドメインソケット

はじめに

UNIX ドメインソケットには、UNIX パスの名前がつきます。たとえば、ソケット名には /tmp/foo などがあります。UNIX ドメインソケットは、単一ホスト上のプロセス間でだけ交信します。UNIX ドメイン上のソケットは、単一ホスト上のプロセス間の交信にしか使用できないため、ネットワークプロトコルの一部とは見なされません。

ソケットタイプでは、ユーザーが認識できる通信プロパティを定義します。インターネットドメインソケットを使用すると、TCP/IP トランスポートプロトコルにアクセスできます。インターネットドメインは、AF_INET という値で識別します。ソケットは、同じドメイン内にあるソケットとだけデータをやりとりします。

ソケットの作成

socket(3SOCKET) 呼び出しを使用すると、指定のファミリおよび指定のタイプのソケットを作成できます。

s = socket(family, type, protocol);

プロトコルが未指定 (値が 0) の場合、要求したソケットタイプをサポートするプロトコルがシステムによって選択され、ソケットハンドル (ファイル記述子) が返されます。

ファミリは、sys/socket.h に定義されている定数の 1 つで指定します。AF_suite という定数には、表 2-1 に示されている名前を解釈する際に使用するアドレス形式を指定します。

次のコードでは、マシン内部で使用されるデータグラムソケットを作成します。

s = socket(AF_UNIX, SOCK_DGRAM, 0);

プロトコルは、通常、デフォルトのもの (protocol 引数に 0 を指定する) を使用します。

ローカル名のバインド

ソケットは、その作成時には名前がありません。遠隔プロセスは、ソケットにアドレスがバインドされるまでソケットを参照できません。通信プロセスは、アドレスを介して接続されます。UNIX ファミリでは、接続は、通常、1 つまたは 2 つのパス名からなります。UNIX ファミリのソケットは、必ずしも名前にバインドされる必要はありませんが、バインドされると、local pathname または foreign pathname といった順序セットを複製することができません。パス名では、既存のファイルを参照できません。

bind(3SOCKET) 呼び出しを使用すると、プロセスは、ソケットのローカルアドレスを指定できます。これによって、local pathname が決定します。一方、connect(3SOCKET)accept(3SOCKET) は、遠隔側アドレスを固定することでソケットの接続を完了します。bind(3SOCKET) は、次のように使用します。

bind (s, name, namelen);

s は、ソケットハンドルです。バインド名は、バイト文字列であり、サポートするプロトコル (複数も可) がこれを解釈します。UNIX ファミリ名には、パス名とファミリが含まれます。例では、UNIX ファミリソケットに /tmp/foo という名前をバインドしています。

#include <sys/un.h>
 ...
struct sockaddr_un addr;
 ...
strcpy(addr.sun_path, "/tmp/foo");
addr.sun_family = AF_UNIX;
bind (s, (struct sockaddr *) &addr,
		strlen(addr.sun_path) + sizeof (addr.sun_family));

AF_UNIX というソケットアドレスの大きさを判定する場合には、ヌル (null) バイトがカウントされません。このため、strlen(3C) の使用をお勧めします。

addr.sun_path で参照されるファイル名は、システムファイル名空間でソケットとして作成されます。呼び出し側は、addr.sun_path が作成されるディレクトリに書き込み許可を持っていなければなりません。このファイルは、不要になったら呼び出し側が削除しなければなりません。AF_UNIX ソケットは、unlink(1M) で削除できます。

接続の確立

通常、接続の確立は非対称に行われます。1 つのプロセスは、クライアントとして機能し、もう一方のプロセスはサーバーとして機能します。サーバーは、サービスに関連付けられた既知のアドレスにソケットをバインドし、接続要求のためにソケットをブロックします。すると、無関係のプロセスがサーバーに接続できます。クライアントは、サーバーのソケットへの接続を起動することでサーバーにサービスを要求します。クライアント側では、connect(3SOCKET) 呼び出しによって接続を起動できます。UNIX ファミリは、これを次のように表現します。

struct sockaddr_un server;
		server.sun.family = AF_UNIX;
		 ...
		connect(s, (struct sockaddr *)&server, strlen(server.sun_path) 
         + sizeof (server.sun_family));

接続エラーについては、「接続エラー」を参照してください。「データ転送」では、データの転送方法を示します。「ソケットを閉じる」では、ソケットのクローズ方法を示します。