Linux
2019-03-06
man-pages-ru
Russian man pages from the Linux Documentation Project
manpages-dev
Manual pages about using GNU/Linux for development
man-pages
Linux kernel and C library user-space interface documentation
ИМЯ
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]; }
sa_family_t sa_family;
char sa_data[14]; }
Единственным смыслом этой структуры является преобразование указателя структуры, передаваемого в addr, чтобы избежать предупреждений компилятора. См. ПРИМЕР ниже.
ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При успешном выполнении возвращается 0. В случае ошибки возвращается -1, а errno устанавливается в соответствующее значение.
ОШИБКИ
EACCES | Адрес защищён, или пользователь не является суперпользователем. |
EADDRINUSE | |
Указанный адрес уже используется. | |
EADDRINUSE | |
(доменные сокеты Интернета) В структуре адреса сокета указан номер порта равный нулю, но при попытке привязаться к эфемеридному порту, было определено, что все номера в диапазоне эфемеридных портов уже используются. Смотрите обсуждение /proc/sys/net/ipv4/ip_local_port_range в ip(7). | |
EBADF | Значение sockfd не является правильным файловым дескриптором. |
EINVAL | Сокет уже привязан к адресу. |
EINVAL | Некорректное значение addrlen, или в addr указан некорректный адрес для этого доменного сокета. |
ENOTSOCK | |
Файловый дескриптор sockfd указывает не на каталог. | |
Следующие ошибки только для сокетов домена UNIX (AF_UNIX): | |
EACCES | Поиск запрещён из-за одного из частей префикса пути (см. также path_resolution(7)). |
EADDRNOTAVAIL | |
Запрошен несуществующий интерфейс или запрашиваемый адрес не является локальным. | |
EFAULT | addr указывает вне адресного пространства, доступного пользователю. |
ELOOP | При определении addr превышено количество переходов по символьной ссылке. |
ENAMETOOLONG | |
Аргумент addr слишком большой. | |
ENOENT | Компонент из каталожного префикса пути сокета не существует. |
ENOMEM | Недостаточное количество памяти ядра. |
ENOTDIR | |
Компонент в префиксе пути не является каталогом. | |
EROFS | Попытка создания inode сокета на файловой системе, доступной только для чтения. |
СООТВЕТСТВИЕ СТАНДАРТАМ
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)
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;
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");
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);
/* Очистка структуры */
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");
sizeof(struct sockaddr_un)) == -1)
handle_error("bind");
if (listen(sfd, LISTEN_BACKLOG) == -1)
handle_error("listen");
handle_error("listen");
/* Теперь мы можем принимать входящие соединения по одному
с помощью accept(2) */
с помощью 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");
cfd = accept(sfd, (struct sockaddr *) &peer_addr,
&peer_addr_size);
if (cfd == -1)
handle_error("accept");
/* Код обработки входящего соединения(й)... */
СМОТРИТЕ ТАКЖЕ
REFERENCED BY
authbind(1), authbind-helper(8), sctp_bindx(3), sctp(7), accept(2), connect(2), getpeername(2), getsockname(2), listen(2), socket(2), socketcall(2), bindresvport(3), getaddrinfo(3), getifaddrs(3), if_nameindex(3), services(5), ddp(7), inotify(7), ip(7), ipv6(7), netlink(7), packet(7), raw(7), sock_diag(7), socket(7), tcp(7), udp(7), unix(7), dircproxy(1), atalk(4), privbind(1), socket(1), tac_plus(8), tcptraceroute.mt(1), msocket(2viewos), vsock(7), tcptraceroute(1), rds(7)