BIND(2) | Руководство программиста Linux | 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() назначает адрес, заданный в addr, сокету, указываемому дескриптором файла sockfd. В аргументе addrlen задаётся размер структуры адреса (в байтах), на которую указывает addr. В силу традиции, эта операция называется «присваивание сокету имени».
Обычно, сокету типа SOCK_STREAM нужно назначить локальный адрес с помощью bind() до того, как он сможет принимать соединения (см. accept(2)).
Правила, используемые при привязке имён, отличаются в разных семействах адресов. Подробности см. в соответствующем справочных страницах в разделе 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, чтобы избежать предупреждений компилятора. См. ПРИМЕР ниже.
При успешном выполнении возвращается 0. В случае ошибки возвращается -1, а errno устанавливается в соответствующее значение.
Следующие ошибки только для сокетов домена UNIX (AF_UNIX):
POSIX.1-2001, POSIX.1-2008, SVr4, 4.4BSD, (bind() впервые появился в 4.2BSD).
В POSIX.1 не требуется включение <sys/types.h>, и этот заголовочный файл не требуется в Linux. Однако, для некоторых старых реализаций (BSD) данный файл нужен, и в переносимых приложениях для предосторожности, вероятно, лучше его указать.
Описание типа socklen_t смотрите в accept(2).
Не описываются возможности, связанные с работой прозрачных прокси.
Пример использования bind() с сокетами домена Internet можно найти в getaddrinfo(3).
Следующий пример показывает как привязать потоковый сокет к домену UNIX (AF_UNIX) и принимать соединения:
#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(struct sockaddr_un)); /* Очистка структуры */ 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(struct sockaddr_un)) == -1) handle_error("bind"); if (listen(sfd, LISTEN_BACKLOG) == -1) handle_error("listen"); /* Теперь мы можем принимать входящие соединения по одному с помощью accept(2) */ peer_addr_size = sizeof(struct sockaddr_un); cfd = accept(sfd, (struct sockaddr *) &peer_addr, &peer_addr_size); if (cfd == -1) handle_error("accept"); /* Код обработки входящего соединения(й)... */ /* Если имя пути сокета, MY_SOCK_PATH, больше не требуется, то его нужно удалить с помощью unlink(2) или 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)
2019-03-06 | Linux |