Опубликован: 15.06.2004 | Доступ: свободный | Студентов: 2557 / 712 | Оценка: 4.35 / 3.96 | Длительность: 27:47:00
ISBN: 978-5-9556-0011-6
Лекция 11:

Сетевые средства

Функции для работы с сокетами

Работа с сокетами как оконечными точками при взаимодействии процессов начинается с их ( сокетов ) создания посредством функции socket() (см. листинг 11.19). Она возвращает открытый файловый дескриптор, который может быть использован в последующих вызовах функций, оперирующих с сокетами. В том же листинге показано описание функции socketpair(), создающей пару сокетов с установленным между ними соединением.

#include <sys/socket.h>
int socket (int af, int type, int protocol);
int socketpair (int af, int type, 
                int protocol, int sds [2]);
Листинг 11.19. Описание функций socket() и socketpair().

Аргумент af задает адресное семейство создаваемого сокета, аргумент type - тип, аргумент protocol - конкретный протокол ( 0 обозначает неспецифицированный подразумеваемый протокол, пригодный для запрошенного типа). Напомним, что подходящие значения для аргументов af, type и protocol можно получить с помощью описанной ранее функции getaddrinfo().

Функция socketpair() по назначению аналогична pipe(), только организуется не безымянный канал, а пара соединенных, безымянных (не привязанных к каким-либо адресам), идентичных сокетов , открытые файловые дескрипторы которых помещаются в массив sds. Обычно она используется для адресного семейства AF_UNIX ; поддержка для других семейств не гарантируется.

После того как посредством функции bind() (см. листинг 11.20) создан сокет, идентифицируемый дескриптором sd, ему присваивают локальный адрес, заданный аргументом address ( address_len - длина структуры sockaddr, на которую указывает address ). Источником локальных адресов для сокетов может служить вышеупомянутая функция getaddrinfo().

#include <sys/socket.h>
int bind (int sd, const struct sockaddr 
          *address, socklen_t address_len);
Листинг 11.20. Описание функции bind().

Опросить присвоенный локальный адрес (его иногда называют именем сокета ) можно с помощью функции getsockname() (см. листинг 11.21): она помещает его в структуру sockaddr, на которую указывает аргумент address, а длину адреса записывает по указателю address_len.

#include <sys/socket.h>
int getsockname 
   (int sd, struct sockaddr *restrict address,
    socklen_t *restrict address_len);
Листинг 11.21. Описание функции getsockname().

Если сокет ориентирован на режим с установлением соединения (имеет тип SOCK_STREAM ), то, воспользовавшись функцией listen() (см. листинг 11.22), его следует пометить как готового принимать соединения (" слушающего ").

#include <sys/socket.h>
int listen (int sd, int backlog);
Листинг 11.22. Описание функции listen().

Аргумент backlog сообщает операционной системе рекомендуемую длину очереди соединений, ожидающих обработки слушающим сокетом. Реализация должна поддерживать значения аргумента backlog вплоть до конфигурационной константы SOMAXCONN, определенной в заголовочном файле <sys/socket.h>. ОС имеет право установить длину очереди меньше рекомендуемой. При неположительном значении backlog очередь будет иметь зависящую от реализации минимальную длину.

Прием соединений выполняет функция accept() (см. листинг 11.23). Она выбирает первое соединение из очереди, ассоциированной с заданным дескриптором sd слушающим сокетом, создает новый сокет с теми же адресным семейством, типом и протоколом и возвращает в качестве результата его файловый дескриптор.

#include <sys/socket.h>
int accept 
   (int sd, struct sockaddr *restrict address,
    socklen_t *restrict address_len);
Листинг 11.23. Описание функции accept().

Если значение аргумента address отлично от пустого указателя, то в структуру sockaddr, на которую указывает address, помещается адрес сокета, пытающегося установить соединение. По указателю address_len при обращении к функции accept() должна быть задана длина переданной структуры sockaddr, а на выходе туда записывается длина адреса партнера по взаимодействию.

Если очередь соединений, ожидающих обработки слушающим сокетом, пуста и для дескриптора sd не установлен флаг O_NONBLOCK, то вызвавший функцию accept() процесс (поток управления) блокируется до появления подобного соединения. При непустой очереди функция select() сообщит о готовности дескриптора sd к чтению.

Другая сторона, т. е. потенциальный партнер по взаимодействию, инициирует соединение с помощью функции connect() (см. листинг 11.24). Аргументы address и address_len стандартным образом задают адрес сокета (как правило, слушающего ), с которым необходимо установить соединение.

#include <sys/socket.h>
int connect (int sd, const struct sockaddr 
     *address, socklen_t address_len);
Листинг 11.24. Описание функции connect().
Антон Коновалов
Антон Коновалов

В настоящее время актуальный стандарт - это POSIX 2008 и его дополнение POSIX 1003.13
Планируется ли актуализация материалов данного очень полезного курса?