bind(2)

NAZWA
bind - przywiązuje nazwę do gniazda

BIBLIOTEKA
Standardowa biblioteka C (libc, -lc)

SKŁADNIA
#include <sys/socket.h>

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

OPIS
Gdy tworzone jest gniazdo za pomocą socket(2), istnieje ono w przestrzeni nazw (rodzinie adresów), lecz nie ma przypisanego adresu. bind() przypisuje adres określony w addr do gniazda odnoszącego się do deskryptora pliku sockfd. addrlen określa rozmiar, w bajtach, struktury adresowej na którą wskazuje addr. Tradycyjnie operacja ta była nazywana "przypisaniem nazwy do gniazda".

Normalnie, zanim gniazdo SOCK_STREAM będzie mogło odbierać połączenia (zobacz accept(2)), niezbędne jest przypisanie mu lokalnego adresu za pomocą bind().

Reguły dotyczące przywiązywania nazw są różne w różnych rodzinach adresów. Szczegółowe informacje znajdują się na stronach podręcznika systemowego w sekcji 7. Dla AF_INET zobacz ip(7), dla AF_INET6 zobacz ipc6(7), dla AF_UNIX zobacz unix(7), dla AF_APPLETALK zobacz ddp(7), dla AF_PACKET zobacz packet(7), dla AF_X25 zobacz x25(7), a dla AF_NETLINK zobacz netlink(7).

Faktyczna struktura przekazywana jako argument addr będzie zależała od rodziny adresowej. Struktura sockaddr jest zdefiniowana podobnie do:

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

Jedyną funkcją tej struktury jest rzutowanie wskaźnika struktury przekazanego w addr, aby uniknąć ostrzeżeń kompilatora. Zob. PRZYKŁADY poniżej.

WARTOŚĆ ZWRACANA
Po pomyślnym zakończeniu zwracane jest zero. Po błędzie zwracane jest -1 i ustawiane errno, wskazując błąd.

BŁĘDY

EACCES
    Adres jest chroniony, a użytkownik nie jest superużytkownikiem.

EADDRINUSE
    Podany adres już jest wykorzystywany.

EADDRINUSE
    (gniazda domeny Internet) Podano zero jako numer portu w strukturze adresu gniazda, lecz przy próbie skojarzenia z portem dynamicznym (efemerycznym), okazało się, że wszystkie numery portów w zakresie portów dynamicznych są aktualnie używane. Więcej informacji w opisie pliku /proc/sys/net/ipv4/ip_local_port_range w podręczniku ip(7).

EBADF
    sockfd nie jest prawidłowym deskryptorem pliku.

EINVAL
    Gniazdo jest już skojarzone z adresem.

EINVAL
    addrlen jest nieprawidłowe lub addr nie jest prawidłowym adresem dla tej domeny gniazda.

ENOTSOCK
    Deskryptor pliku sockfd nie odnosi się do gniazda.

Następujące błędy odnoszą się do gniazd domeny UNIX-owej (AF_UNIX):

EACCES
    Brak praw do przeszukiwania dla składowej ścieżki (zob. także path_resolution(7)).

EADDRNOTAVAIL
    Zażądano nieistniejącego interfejsu lub żądany adres nie jest adresem lokalnym.

EFAULT
    addr wskazuje poza dostępną dla użytkownika przestrzeń adresową.

ELOOP
    Podczas rozwiązywania addr napotkano zbyt wiele dowiązań symbolicznych.

ENAMETOOLONG
    addr jest zbyt długie.

ENOENT
    Fragment ścieżki gniazda odnoszący się do któregoś z katalogów nie istnieje.

ENOMEM
    Brak pamięci jądra.

ENOTDIR
    Składowa ścieżki nie jest katalogiem.

EROFS
    I-węzeł gniazda rezyduje na systemie plików przeznaczonym tylko do odczytu.

STANDARDY
POSIX.1-2008.

HISTORIA
POSIX.1-2001, SVr4, 4.4BSD (bind() pojawiło się pierwotnie w 4.2BSD).

USTERKI
Nie opisano opcji przezroczystych proxy.

PRZYKŁADY
Przykładowy program używający bind() z gniazdami domeny Internet można znaleźć w getaddrinfo(3).

Następujący przykład pokazuje sposób na skojarzenie gniazda strumieniowego w domenie uniksowej (AF_UNIX) i akceptować połączenia:

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

    #define MY_SOCK_PATH "/somepath"
    #define LISTEN_BACKLOG 50

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

    int
    main(void)
    {
        int                 sfd, cfd;
        socklen_t           peer_addr_size;
        struct sockaddr_un  my_addr, peer_addr;

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

        memset(&my_addr, 0, sizeof(my_addr));
        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");

        /* Teraz możemy akceptować nadchodzące połączenia,
           po jednym naraz, za pomocą accept(2). */

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

        /* Kod do obsługi nadchodzących połączeń... */

        if (close(sfd) == -1)
            handle_error("close");

        if (unlink(MY_SOCK_PATH) == -1)
            handle_error("unlink");
    }

ZOBACZ TAKŻE
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)

TŁUMACZENIE
Tłumaczenie niniejszej strony podręcznika: Przemek Borys <pborys@dione.ids.pl>, Andrzej Krzysztofowicz <ankry@green.mf.pg.gda.pl> i Michał Kułach <michal.kulach@gmail.com>

Niniejsze tłumaczenie jest wolną dokumentacją. Bliższe informacje o warunkach licencji można uzyskać zapoznając się z GNU General Public License w wersji 3 (https://www.gnu.org/licenses/gpl-3.0.html) lub nowszej. Nie przyjmuje się ŻADNEJ ODPOWIEDZIALNOŚCI.

Błędy w tłumaczeniu strony podręcznika prosimy zgłaszać na adres listy dyskusyjnej manpages-pl-list@lists.sourceforge.net.