запросов read()
и write()
, как и любой другой файловый дескриптор. Когда процесс завершает работу с сокетом, его необходимо закрыть через функцию close()
для того, чтобы освободить все ресурсы, ассоциированные с ним.
В настоящем разделе представлены основные системные вызовы для создания и инициализации сокетов для любого протокола. Для того чтобы не зависеть от протоколов, информация в некоторой степени абстрагирована, по этой же причине мы не приводим примеры. Следующие два раздела посвящены применению сокетов в двух различных протоколах (домен Unix и TCP/IP). Здесь вы найдете подробные примеры использования большинства системных вызовов, описанных ниже.
17.3.1. Создание сокета
Новые сокеты создаются системным вызовом socket()
, который возвращает файловый дескриптор для
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
Подобно open()
, функция socket()
возвращает значение меньше 0, если имела место ошибка, и файловый дескриптор, больший или равный нулю, если все прошло благополучно. Три параметра устанавливают протокол, который нужно использовать.
Первый параметр указывает семейство протоколов и, как правило, принимает одно из значений, перечисленных в табл. 17.1.
Следующий параметр type
может иметь одно из значений: SOCK_STREAM
, SOCK_DGRAM
или SOCK_RAW
.[119] Здесь SOCK_STREAM
указывает потоковый протокол из данного семейства, a SOCK_DGRAM
специфицирует дейтаграммный протокол из того же семейства. Параметр SOCK_RAW
предоставляет возможность передавать пакеты прямо в драйвер сетевого устройства, что позволяет пользовательским приложениям поддерживать сетевые протоколы, которые не воспринимаются ядром.
Последний параметр устанавливает протокол для использования с учетом всех ограничений, введенных первыми двумя параметрами. Как правило, значение этого параметра равно 0, что позволяет ядру использовать стандартный протокол установленного типа из указанного семейства. В табл. 17.2 перечислены некоторые допустимые протоколы для семейства PF_INET
. Стандартными протоколами здесь считаются IPPROTO_TCP
(потоковый) и IPPROTO_UDP
(дейтаграммный).
Таблица 17.2. Протоколы IP
Протокол | Описание |
---|---|
IPPROTO_ICMP | Internet Control Message Protocol (протокол управляющих сообщений в сети Internet) для IPv4. |
IPPROTO_ICMPV6 | Internet Control Message Protocol (протокол управляющих сообщений в сети Internet) для IPv6. |
IPPROTO_IPIP | Тоннели IPIP |
IPPROTO_IPV6 | Заголовки IPv6. |
IPPROTO_RAW | Пакеты Raw IP. |
IPPROTO_TCP | Transmission Control Protocol (TCP) (протокол управления передачей). |
IPPROTO_UDP | User Datagram Protocol (UDP) (протокол передачи дейтаграмм пользователя). |
17.3.2. Установка соединений
После создания потокового сокета его необходимо присоединить к чему-то часто используемому. Установка соединений сокетов является в большой степени несимметричной задачей, поскольку каждая сторона проводит соединение по-разному. Одна сторона получает сокет, который готов к соединению, и затем ожидает кого-либо для того, чтобы присоединиться к нему. Эту функцию, как правило, выполняют серверные приложения, которые однажды активизируются и постоянно продолжают работать, ожидая подключения со стороны других процессов.
Клиентские процессы, в свою очередь, создают сокет, сообщают системе адрес, к которому они хотят подключиться, и после этого пытаются установить соединение. Как только сервер (ожидающий клиента) принимает попытку соединения, устанавливается соединение между двумя сокетами. После этого сокет может использоваться для двусторонней связи.
17.3.3. Связывание адреса с сокетом
И серверный, и клиентский процессы должны сообщить системе, какой адрес использовать для сокета. Прикрепление адреса к локальной стороне сокета называется связыванием