Шрифт:
Системный вызов
socket
возвращает дескриптор, во многом похожий на низкоуровневый файловый дескриптор. Когда сокет подключен к концевой точке другого сокета, для отправки и получения данных с помощью сокетов можно применять системные вызовы read
и write
с дескриптором сокета. Системный вызов close
используется для удаления сокетного соединения. Адреса сокетов
Каждый домен сокетов требует своего формата адресов. В домене
AF_UNIX
адрес описывается структурой sockaddr_un
, объявленной в заголовочном файле sys/un.h:
struct sockaddr_un {
sa_family_t sun_family; /* AF_UNIX */
char sun_path[]; /* Путь к файлу */
};
Для того чтобы адреса разных типов могли передаваться в системные вызовы для обработки сокетов, все адресные форматы описываются похожей структурой, которая начинается с поля (в данном случае
sun_family
), задающего тип адреса (домен сокета). В домене AF_UNIX
адрес задается именем файла в поле структуры sun_path
. В современных системах Linux тип
sa_family_t
, описанный в стандарте X/Open как объявляемый в заголовочном файле sys/un.h, интерпретируется как тип short
. Кроме того, размер pathname
, задаваемого в поле sun_path
, ограничен (в Linux указывается 108 символов; в других системах может применяться именованная константа, например, UNIX_MAX_PATH
). Поскольку размер адресной структуры может меняться, многие системные вызовы сокетов требуют или предоставляют на выходе длину, которая будет использоваться для копирования конкретной адресной структуры. В домене
AF_INET
адрес задается с помощью структуры с именем sockaddr_in
, определенной в файле netinet/in.h, которая содержит как минимум следующие элементы:
struct sockaddr_in {
short int sin_family; /* AF_INET */
unsigned short int sin_port; /* Номер порта */
struct in_addr sin_addr; /* Интернет-адрес */
};
Структура IP-адреса типа in_addr определена следующим образом:
struct in_addr {
unsigned long int s_addr;
};
Четыре байта IP-адреса образуют одно 32-разрядное значение. Сокет домена
AF_INET
полностью описывается IP-адресом и номером порта. С точки зрения приложения все сокеты действуют как файловые дескрипторы, и их адреса задаются уникальными целочисленными значениями. Именование сокета
Для того чтобы сделать сокет (созданный с помощью вызова
socket
) доступным для других процессов, серверная программа должна присвоить сокету имя. Сокеты домена AF_UNIX
связаны с полным именем файла в файловой системе, как вы видели в программе-примере server1. Сокеты домена AF_INET
связаны с номером IP-порта.
#include <sys/socket.h>
int bind(int socket, const struct sockaddr *address, size_t address len);
Системный вызов
bind
присваивает адрес, заданный в параметре address
, неименованному сокету, связанному с дескриптором сокета socket
. Длина адресной структуры передается в параметре address_len
: Длина и формат адреса зависят от адресного семейства. В системном вызове
bind
указатель конкретной адресной структуры должен быть приведен к обобщенному адресному типу (struct sockaddr*)
. В случае успешного завершения
bind
возвращает 0. Если он завершается аварийно, возвращается -1, и переменной errno
присваивается одно из значений, перечисленных в табл. 15.2. Таблица 15.2
Значение errno | Описание |
---|---|
EBADF | Неверный файловый дескриптор |
ENOTSOCK | Файловый дескриптор не ссылается на сокет |
EINVAL | Файловый дескриптор ссылается на сокет, уже получивший имя |
EADDRNOTAVAIL | Недопустимый адрес |
EADDINUSE | У адреса уже есть связанный с ним сокет |
Для сокетов домена AF_UNIX есть несколько дополнительных значений | |
EACCESS | Невозможно создать имя в файловой системе из-за прав доступа |
ENOTDIR , ENAMETOOLONG | Означает недопустимое имя файла |