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

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

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

Функция connect() ограничится фиксацией адреса сокета, взаимодействующего с заданным аргументом sd, если тип сокета не требует установления соединения. В частности, для сокетов типа SOCK_DGRAM таким способом можно специфицировать адреса отправляемых (с помощью функции send() ) и принимаемых (посредством обращения к функции recv() ) датаграмм.

Когда в качестве аргумента address передается пустой указатель, адрес взаимодействующего сокета сбрасывается.

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

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

Сокет оказывается в неспецифицированном состоянии, если функция connect() завершается неудачей по другим причинам. Приложения, соответствующие стандарту POSIX-2001, должны закрыть файловый дескриптор sd и создать новый сокет для продолжения попыток установить соединение.

После асинхронного установления соединения функции select() и poll() сообщат, что файловый дескриптор sd готов к записи.

Функция poll(), позволяющая мультиплексировать ввод/вывод в пределах набора файловых дескрипторов, была описана нами выше. Имеющая сходную направленность (но входящая в обязательную часть стандарта POSIX-2001) функция select() и ее недавно введенный аналог pselect() представлены в листинге 11.25.

#include <sys/select.h>
int pselect (int nfds, fd_set *restrict readfds, fd_set *restrict writefds, 
             fd_set *restrict errorfds, const struct timespec *restrict timeout, 
			 const sigset_t *restrict sigmask);
int select (int nfds, fd_set *restrict readfds, fd_set *restrict writefds, 
            fd_set *restrict errorfds, struct timeval *restrict timeout);
void FD_CLR (int fd, fd_set *fdset);
int FD_ISSET (int fd, fd_set *fdset);
void FD_SET (int fd, fd_set *fdset);
void FD_ZERO (fd_set *fdset);
Листинг 11.25. Описание функций семейства select*().

Если значение аргумента readfds ( writefds, errorfds ) функции pselect() отлично от NULL, оно ссылается на объект типа fd_set, который на входе специфицирует набор файловых дескрипторов, проверяемых на готовность к чтению (или к записи, или к обработке исключительных ситуаций), а на выходе указывает, какие из них успешно прошли проверку. Аргумент nfds задает границу проверяемых дескрипторов (они являются небольшими целыми числами): дескриптор подлежит проверке, если его значение находится в пределах от 0 до (nfds - 1) включительно.

Стандарт POSIX-2001 определяет тип fd_set как абстрактный. Для работы со значениями этого типа служат макросы FD_ZERO() (сделать набор пустым), FD_SET() (добавить дескриптор к набору), FD_CLR() (удалить дескриптор из набора), FD_ISSET() (проверить принадлежность дескриптора набору). Значение именованной константы FD_SETSIZE равно максимально допустимому числу дескрипторов в наборе.

В качестве результата pselect() возвращается общее количество дескрипторов во всех трех наборах, успешно прошедших проверку.

При отсутствии готовых дескрипторов вызывающий процесс блокируется, пока таковые не появятся, или пока не истечет заданное аргументом timeout время ожидания, или пока ожидание не будет прервано сигналом. Пустой указатель в качестве значения timeout означает бесконечное ожидание, а нулевые значения полей структуры timespec - отсутствие блокировки. Реализация может накладывать ограничение на максимальное время ожидания, но оно не должно быть меньше тридцати одного дня.

Если значение аргумента sigmask отлично от пустого указателя, функция pselect() на входе заменяет маску сигналов процесса на заданную, а на выходе восстанавливает прежнюю маску.

Функция pselect() поддерживает обычные файлы, терминалы и псевдотерминалы, каналы и сокеты.

Функция select() эквивалентна pselect() со следующими оговорками.

  1. Для функции select() время ожидания задается в секундах и микросекундах в виде структуры типа timeval, а для pselect() - в секундах и наносекундах как аргумент типа struct timespec.
  2. У функции select() нет аргумента - маски сигналов, что эквивалентно пустому указателю в качестве значения аргумента sigmask функции pselect().
  3. В случае успешного завершения функция select() может модифицировать структуру, на которую указывает аргумент timeout.

С сокетами могут быть ассоциированы опции, влияющие на их функционирование. Значения этих опций можно опросить или изменить с помощью функций getsockopt() и setsockopt() (см. листинг 11.26).

#include <sys/socket.h>
int getsockopt (int sd, int level, 
      int option_name, 
      void *restrict option_value, 
      socklen_t *restrict option_len);
int setsockopt (int sd, int level, 
      int option_name, 
      const void *option_value, 
      socklen_t option_len);
Листинг 11.26. Описание функций getsockopt() и setsockopt().
Антон Коновалов
Антон Коновалов

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