bind() - ソケットへの名前の結合

標準

標準/拡張機能 C/C++ 依存項目

XPG4.2
Single UNIX Specification、バージョン 3

両方  

形式

X/Open
#define _XOPEN_SOURCE_EXTENDED 1
#include <sys/socket.h>

int bind(int socket, const struct sockaddr *address, socklen_t address_len);
バークレー・ソケット
#define _OE_SOCKETS
#include <sys/types.h>
#include <sys/socket.h>

int bind(int socket, struct sockaddr *address, int address_len);

機能説明

bind() 関数は、固有のローカル名を socket 記述子のソケットに結合します。socket() 呼び出しの後で、記述子には、関連付けられた名前がありません。記述子は、socket() が呼び出されたときに指定された特定のアドレス・ファミリーに所属します。名前の正確な形式は、アドレス・ファミリーに依存します。
パラメーター
説明
socket
直前の socket() 呼び出しで戻されたソケット記述子。
address
socket に結合される名前が入っている sockaddr 構造体を指すポインター。
address_len
address のサイズ (バイト単位)。

socket パラメーターは、socket() 呼び出しにより作成された不特定型のソケット記述子です。

address パラメーターは、socket に結合される名前が入っている、バッファーを指すポインターです。address_len パラメーターは、address が示す バッファーのサイズ (バイト単位) です。AF_UNIX の場合、この関数は、ソケットをクローズする以外にあとで リンク解除する必要のあるファイルを作成します。

AF_INET ドメインで作成されたソケット記述子

ソケット記述子 socket が AF_INET ドメインで作成された 場合、名前バッファーの形式は、組み込みファイル の netinet/in.h に定義されているよう に、sockaddr_in であると想定されます。
struct in_addr
{
        ip_addr_t s_addr;
};

 struct sockaddr_in {
     unsigned char  sin_len;
     unsigned char  sin_family;
     unsigned short sin_port;
     struct in_addr sin_addr;
     unsigned char  sin_zero[8];

};

sin_family フィールドは、AF_INET に設定する必要があります。

sin_port フィールドは、アプリケーションの結合先である ポートに設定します。このフィールドは、ネットワーク・バイト順に指定しなければ なりません。sin_port0 に設定すると、呼び出し元は、使用可能なポートを割り当てるために、このフィールドをシステムに残します。アプリケーションは、割り当てられたポート番号を見つけるのに、getsockname() を呼び出すことができます。

sin_addr.s_addr フィールドは IP アドレスに設定し、ネットワーク・バイト順に指定する必要があります。複数のネットワーク・インターフェースを持つホスト (マルチホーム・ホストと呼ばれる) では、呼び出し元は、結合先のインターフェースを選択することができます。次に、(結合された名前と一致する) このインターフェースからの UDP パケットおよび TCP 接続要求だけが、アプリケーションに転送されます。netinet/in.h で定義したように、このフィールドを定数 INADDR_ANY に設定すると、呼び出し元は、ホスト上のすべてのネットワーク・インターフェースにソケットが結合されるよう要求します。続いて、(結合された名前と一致する) すべての インターフェースからの UDP パケットおよび TCP 接続が、アプリケーションに転送されます。サーバーが複数のネットワークにサービスを提供する ときには、この方法が重要です。アドレスを未指定のままにすることにより、サーバーは、要求の到達先のネットワーク・インターフェースにかかわらず、そのポート用に作成された UDP パケットおよび TCP 接続要求 をすべて受け入れることができます。

sin_zero フィールドは使用されません。また、このフィールド は、すべてゼロに設定する必要があります。

AF_INET6 ドメインで作成されたソケット記述子 ソケット記述子 socket が AF_INET6 ドメインで作成された 場合、名前バッファーの形式は、組み込みファイル の netinet/in.h に定義されているよう に、sockaddr_in6 であると想定されます。構造体は、以下のように定義されます。
struct sockaddr_in6 {
   uint8_t          sin6_len;
   sa_family_t      sin6_family;
   in_port_t        sin6_port;
   uint32_t         sin6_flowinfo;
   struct in6_addr  sin6_addr;
   uint32_t         sin6_scope_id;
};

sin6_len フィールドは、この構造体のサイズにセットされます。 SIN6_LEN マクロは、使用されている sockaddr_in6 構造体のバージョンを表すように定義されています。

sin6_family フィールドは、これを sockaddr_in6 構造体と識別します。 このフィールドは、バッファーが sockaddr 構造体にキャストされた時に sa_family フィールドをオーバーレイします。このフィールドの値は、AF_INET6 でなければなりません。

sin6_port フィールドは、16 ビット UDP または TCP ポート番号を含んでいます。 このフィールドは、sockaddr_in 構造体の sin_port フィールドと同じ方法で使用されます。ポート番号は、ネットワーク・バイト順に保管されます。

sin6_flowinfo フィールドは、32 ビットのフィールドで、トラフィック・クラスとフロー・ラベルを含んでいます。

sin6_addr フィールドは、単一の in6_addr 構造体です。このフィールドは、 1 つの 128 ビット IPv6 アドレスを保持しています。アドレスは、ネットワーク・バイト順に保管されます。

sin6_scope_id フィールドは、32 ビットの整数で、sin6_addr フィールドに繰り上がったアドレスのスコープに見合ったインターフェースのセットを示します。これは、リンク・スコープ sin6_addr、sin6_scope_id のインターフェース・インデックスです。これは、サイト・スコープ sin6_addr、sin6_scope_id のサイト ID です。

AF_UNIX ドメインで作成されたソケット記述子

ソケット記述子 socket が AF_UNIX ドメインで作成された場合は、名前バッファーの形式は、組み込みファイルの un.h に定義されている sockaddr_un であると想定されます。
 struct sockaddr_un {
    unsigned char  sun_len;
    unsigned char  sun_family;
             char  sun_path[108];        /* pathname */
};

sun_family フィールドは、AF_UNIX に設定します。

sun_path フィールドには、NULL 終了のパス名が 含まれ、sun_len フィールドには、パス名の長さが含まれます。
注 :
  1. AF_UNIX の場合、結合が発行されると、660 のモードでファイル が作成されます。他のユーザーがこのファイルにアクセスできるようにする には、chmod() を発行し、必要に応じてこのモードを変更してください。
  2. AF_UNIX の場合には、結合されたソケットのクローズの際に 、unlink() も使用して、bind() 時に作成 されたファイルを削除する必要があります。
  3. クライアントが bind() で使用するパス名は固有でなければ なりません。
  4. sendto() 呼び出しには、サーバーに関連したパス名を 指定しなければなりません。
  5. AF_INET または AF_INET6 の場合、ユーザーは、1 ~ 1023 までの範囲のポートにバインドするために、適切な特権を持っている必要があります。

C++ の特殊な動作

この関数を C++ で使用するには、_XOPEN_SOURCE_EXTENDED 1 フィーチャー・テスト・マクロを使用する必要があります。

注: bind() 関数は、拡張 ASCII の拡張機能のレベルに依存します。詳細は、拡張 ASCII サポートを参照してください。

戻り値

正常に実行された場合、bind() は、0 を戻します。

正常に実行されなかった場合、bind() は、-1 を戻して、errno を次のいずれかの値に設定します。
エラー・コード
説明
EACCES
許可が拒否されました。
EADDRINUSE
アドレスは既に使用中である。詳細は、getsockopt() - ソケットに関連したオプションの取得で説明して いる SO_REUSEADDR オプション、および setsockopt() - ソケットに関連したオプションの設定で説明して いる SO_REUSEADDR オプションを参照します。
EADDRNOTAVAIL
指定されたアドレスがこのホストでは無効である。例えば、IP アドレスが有効な ネットワーク・インターフェースを指定していません。
EAFNOSUPPORT
アドレス・ファミリーはサポートされていません (それは AF_UNIX、AF_INET、または AF_INET6 ではありません)。
EBADF
socket パラメーターが無効ソケット記述子です。
EINVAL
次の 3 つの状態のいずれかが当てはまる可能性があります。
  • ソケットが既にアドレスに結合済みです。例えば、既に 接続済みのソケットに名前を結合しようとしています。
  • ソケットがシャットダウンされました。
  • bind() 呼び出しで正しくないパラメーターが渡されました。
渡されたパラメーター値を調べて、それらの値が上記で説明されているとおりに指定されていることを確認してください。
EIO
ネットワークまたはトランスポートで障害が発生しました。
ENOBUFS
bind() は、ストレージが不十分なためにバッファーを取得することができません。
ENOTSOCK
記述子はファイル用であり、ソケット用ではありません。
EOPNOTSUPP
指定されたソケットのソケット・タイプが アドレスへの結合をサポートしません。
EPERM
ユーザーは、指定されたポートへの結合を 許可されていません。
以下は、AF_UNIX 専用です。
エラー・コード
説明
EACCES
パス接頭部のコンポーネントが検索許可を拒否します。あるいは、要求された名前が、書き込み許可を拒否するモードで ディレクトリーへの書き込みを要求します。
EDESTADDRREQ
address 引数が NULL ポインターです。
EIO
入出力エラーが発生しました。
ELOOP
address のパス名の変換中に検出された シンボリック・リンクが多すぎます。
ENAMETOOLONG
パス名のコンポーネントが NAME_MAX 文字を超えたか、あるいはパス名全体が PATH_MAX 文字を超えました。
ENOENT
パス名のコンポーネントに既存のファイル名が指定されていないか、またはパス名が空ストリングです。
ENOTDIR
address のパス名のパス接頭部のコンポーネントが ディレクトリーではありません。
EROFS
名前が読み取り専用ファイル・システム上にあります。

以下に示すのは、bind() 呼び出しの例です。要求された名前が予約済みフィールドを何も設定しない ようにするため、構造体を使用する前に構造体をゼロに するのは適切な方法です。

AF_INET ドメインの例

以下の例で、AF_INET ドメインでインターフェースに結合している bind() 呼び出しを示します。 IP アドレスとポートは、ネットワーク・バイト順 でなければなりません。ポートをネットワーク・バイト順にする には、htons() ユーティリティー・ルーチンを 呼び出して、ホスト・バイト順からネットワーク・バイト順 に短整数を変換します。address フィールドは、別のユーティリティー・ ルーチン inet_addr() を使用して設定します。このルーチン は、インターフェースの小数点付き 10 進数アドレスを表す文字ストリングを 受け取って、2 進の IP アドレス表記をネットワーク・バイト順 に戻します。
int rc;
int s;
struct sockaddr_in myname;
/* Bind to a specific interface in the Internet domain */
/* make sure the sin_zero field is cleared */
memset(&myname, 0, sizeof(myname));
myname.sin_family = AF_INET;
myname.sin_addr.s_addr = inet_addr("129.5.24.1"); 
/* specific interface */
myname.sin_port = htons(1024);
⋮
rc = bind(s, (struct sockaddr *) &myname, 
sizeof(myname));
/* Bind to all network interfaces in the Internet domain */
/* make sure the sin_zero field is cleared */
memset(&myname, 0, sizeof(myname));
myname.sin_family = AF_INET;
myname.sin_addr.s_addr = INADDR_ANY; /* specific interface */
myname.sin_port = htons(1024);
⋮
rc = bind(s, (struct sockaddr *) &myname, 
sizeof(myname));
/* Bind to a specific interface in the Internet domain.
   Let the system choose a port                        */
/* make sure the sin_zero field is cleared */
memset(&myname, 0, sizeof(myname));
myname.sin_family = AF_INET;
myname.sin_addr.s_addr = inet_addr("129.5.24.1"); 
/* specific interface */
myname.sin_port = 0;
⋮
rc = bind(s, (struct sockaddr *) &myname, 
sizeof(myname));

AF_UNIX ドメインの例

以下の例で、AF_UNIX ドメインでインターフェースに結合している bind() 呼び出しを示します。
/* Bind to a name in the UNIX domain */
struct sockaddr_un myname;
char socket_name[]="/tmp/socket.for._";
⋮
memset(&myname, 0, sizeof(myname));
myname.sun_family = AF_UNIX;
strcpy(myname.sun_path,socket_name);
myname.sun_len = sizeof(myname.sun_path);
⋮
rc = bind(s, (struct sockaddr *) &myname, SUN_LEN(&myname));