BIND(2)

名前
bind - ソケットに名前をつける

書式
#include <sys/types.h>          /* 「注意」参照 */
#include <sys/socket.h>

int bind(int sockfd, const struct sockaddr *addr,
         socklen_t addrlen);

説明
socket(2) でソケットが作成されたとき、そのソケットは名前空間 (アドレスファミリー) に 存在するが、アドレスは割り当てられていない。 bind() は、ファイルディスクリプター sockfd で参照されるソケットに addr で指定されたアドレスを割り当てる。 addrlen には addr が指すアドレス構造体のサイズをバイト単位で指定する。 伝統的にこの操作は 「ソケットに名前をつける」 と呼ばれる。

SOCK_STREAM ソケットが接続を受け付けられるようにするには (accept(2) を参照)、通常その前に bind() を使用してローカルアドレスを割り当てる必要がある。

名前付けのルールはアドレスファミリーごとに異なっている。詳細な情報は 第 7 章の各マニュアルを参照すること。 AF_INET は ip(7) を、 AF_INET6 は ipv6(7) を、 AF_UNIX は unix(7) を、 AF_APPLETALK は ddp(7) を、 AF_PACKET は packet(7) を、 AF_X25 は x25(7) を、 AF_NETLINK は netlink(7) を参照。

addr 引数に実際にどのような構造体が渡されるかは、 アドレスファミリーに依存する。 sockaddr 構造体は以下のような感じで定義されている:

    struct sockaddr {
        sa_family_t sa_family;
        char        sa_data[14];
    }

この構造体は、 addr に渡される構造体へのポインターをキャストし、 コンパイラの警告メッセージを抑えるためだけに存在する。 下記の「例」を参照。

返り値
成功した場合にはゼロが返される。エラー時には -1 が返され、 errno が適切に設定される。

エラー

EACCES
    そのアドレスは保護されていて、かつユーザーがスーパーユーザーではない。

EADDRINUSE
    指定されたアドレスが既に使用中である。

EADDRINUSE
    (インターネットドメインソケットの場合) ソケットアドレス構造体でポート番号に 0 が指定されたが、 一時ポート (ephemeral port) を割り当てようとした際に、 一時ポートとして使用する範囲のすべてのポート番号が使用中であった。 ip(7) の /proc/sys/net/ipv4/ip_local_port_range の説明を参照。

EBADF
    sockfd が有効なファイルディスクリプターでない。

EINVAL
    ソケットがすでにアドレスに結びつけ (bind) られている。

EINVAL
    addrlen が間違っているか、 addr がこのソケットのドメインで有効なアドレスではない。

ENOTSOCK
    ファイルディスクリプター sockfd がソケットを参照していない。

以下のエラーは UNIXドメイン (AF_UNIX) のソケット特有である:

EACCES
    パス名の構成要素に検索許可 (search permission) がない (path_resolution(7) も参照すること)。

EADDRNOTAVAIL
    存在しないインターフェースが要求されたか、要求されたアドレスが ローカルではなかった。

EFAULT
    addr がユーザーのアクセス可能なアドレス空間の外を指している。

ELOOP
    addr を解決する際に遭遇したシンボリックリンクが多過ぎる。

ENAMETOOLONG
    addr が長過ぎる。

ENOENT
    A component in the directory prefix of the socket pathname does not exist.

ENOMEM
    カーネルに、利用可能なメモリーが十分にない。

ENOTDIR
    パス名の構成要素がディレクトリではない。

EROFS
    ソケット inode が読み込み専用のファイルシステム上にある。

準拠
accept(): POSIX.1-2001, POSIX.1-2008, SVr4, 4.4BSD, (bind() は 4.2BSD で初めて実装された).

注意
POSIX.1 では <sys/types.h> のインクルードは必須とされておらず、 Linux ではこのヘッダーファイルは必要ではない。 しかし、歴史的には、いくつかの実装 (BSD 系) でこのヘッダーファイルが 必要であり、移植性が必要なアプリケーションではこのファイルを インクルードするのが賢明であろう。

For background on the socklen_t type, see accept(2).

バグ
透過的プロキシ (transparent proxy) オプションについて記述していない。

例
インターネットドメインソケットでの bind() の利用例が getaddrinfo(3) に記載されている。

以下の例は、UNIX ドメイン (AF_UNIX) でストリームソケットを bind する方法を示したものである。

    #include <sys/socket.h>
    #include <sys/un.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>

    #define MY_SOCK_PATH "/somepath"
    #define LISTEN_BACKLOG 50

    #define handle_error(msg) \
        do { perror(msg); exit(EXIT_FAILURE); } while (0)

    int
    main(int argc, char *argv[])
    {
        int sfd, cfd;
        struct sockaddr_un my_addr, peer_addr;
        socklen_t peer_addr_size;

        sfd = socket(AF_UNIX, SOCK_STREAM, 0);
        if (sfd == -1)
            handle_error("socket");

        memset(&my_addr, 0, sizeof(my_addr));
                            /* Clear structure */
        my_addr.sun_family = AF_UNIX;
        strncpy(my_addr.sun_path, MY_SOCK_PATH,
                sizeof(my_addr.sun_path) - 1);

        if (bind(sfd, (struct sockaddr *) &my_addr,
                sizeof(my_addr)) == -1)
            handle_error("bind");

        if (listen(sfd, LISTEN_BACKLOG) == -1)
            handle_error("listen");

        /* Now we can accept incoming connections one
           at a time using accept(2) */

        peer_addr_size = sizeof(peer_addr);
        cfd = accept(sfd, (struct sockaddr *) &peer_addr,
                     &peer_addr_size);
        if (cfd == -1)
            handle_error("accept");

        /* Code to deal with incoming connection(s)... */

        /* When no longer required, the socket pathname, MY_SOCK_PATH
           should be deleted using unlink(2) or remove(3) */
    }

関連項目
accept(2), connect(2), getsockname(2), listen(2), socket(2), getaddrinfo(3), getifaddrs(3), ip(7), ipv6(7), path_resolution(7), socket(7), unix(7)

この文書について
この man ページは Linux man-pages プロジェクトのリリース 5.10 の一部である。プロジェクトの説明とバグ報告に関する情報は https://www.kernel.org/doc/man-pages/ に書かれている。