POSIX определяет функцию pselect (повышающую точность таймера с микросекунд до наносекунд) которой передается новый аргумент — указатель на набор сигналов. Это позволяет избежать ситуации гонок (race condition) при перехвате сигналов, о которой мы поговорим более подробно в разделе 20.5.

Функция poll из System V предоставляет функциональность, аналогичную функции select. Кроме того, она обеспечивает дополнительную информацию при работе с потоковыми устройствами. POSIX требует наличия и функции select, и функции poll, но первая распространена шире.

Упражнения

1. Мы говорили, что набор дескрипторов можно присвоить другому набору дескрипторов, используя оператор присваивания языка С. Как это сделать, если набор дескрипторов является массивом целых чисел? (Подсказка: посмотрите на свой системный заголовочный файл <sys/select.h> или <sys/types.h>.)

2. Описывая в разделе 6.3 условия, при которых функция select сообщает, что дескриптор готов для записи, мы указали, что сокет должен быть неблокируемым, для того чтобы операция записи возвратила положительное значение. Почему?

3. Что произойдет с программой из листинга 6.1, если мы поставим слово else перед if в строке 19?

4. В листинге 6.3 добавьте необходимый код, чтобы позволить серверу использовать максимальное число дескрипторов, допустимое ядром (Подсказка: изучите функцию setrlimit.)

5. Посмотрите, что происходит, если в качестве второго аргумента функции shutdown передается SHUT_RD. Возьмите за основу код клиента TCP, представленный в листинге 5.3, и выполните следующие изменения: вместо номера порта SERV_PORT задайте порт 19 (служба chargen, см. табл. 2.1), а также замените вызов функции str_cli вызовом функции pause. Запустите программу, задав IP-адрес локального узла, на котором выполняется сервер chargen. Просмотрите пакеты с помощью такой программы, как, например, tcpdump (см. раздел В.5). Что происходит?

6. Почему приложение должно вызывать функцию shutdown с аргументом SHUT_RDWR, вместо того чтобы просто вызвать функцию close?

7. Что происходит в листинге 6.4, когда клиент отправляет RST для завершения соединения?

8. Перепишите код, показанный в листинге 6.5, чтобы вызывать функцию sysconf для определения максимального числа дескрипторов и размещения соответствующего массива client в памяти.

Глава 7

Параметры сокетов

7.1. Введение

Существуют различные способы получения и установки параметров сокетов:

■ функции getsockopt и setsockopt;

■ функция fcntl;

■ функция ioctl.

Эту главу мы начнем с описания функций getsockopt и setsockopt. Далее мы приведем пример, в котором выводятся заданные по умолчанию значения параметров, а затем дадим подробное описание всех параметров сокетов. Мы разделили описание параметров на следующие категории: общие, IPv4, IPv6, TCP и SCTP. При первом прочтении главы можно пропустить подробное описание параметров и при необходимости прочесть отдельные разделы, на которые даны ссылки. Отдельные параметры подробно описываются в дальнейших главах, например параметры многоадресной передачи IPv4 и IPv6 мы обсуждаем в разделе 19.5.

Мы также рассмотрим функцию fcntl, поскольку она реализует предусмотренные стандартом POSIX возможности отключить для сокета блокировку ввода-вывода, включить управление сигналами, а также установить владельца сокета. Функцию ioctl мы опишем в главе 17.

7.2. Функции getsockopt и setsockopt

Эти две функции применяются только к сокетам.

#include <sys/socket.h>

int getsockopt(int <i>sockfd</i>, int <i>level</i>, int <i>optname</i>, void *<i>optval</i>, socklen_t *<i>optlen</i>);

int setsockopt(int <i>sockfd</i>, int <i>level</i>, int <i>optname</i>, const void *<i>optval</i>, socklen_t <i>optlen</i>);

<i>Обе функции возвращают 0 в случае успешного завершения, -1 в случае ошибки</i>

Переменная sockfd должна ссылаться на открытый дескриптор сокета. Переменная level определяет, каким кодом должен интерпретироваться параметр: общими программами обработки сокетов или зависящими от протокола программами (например, IPv4, IPv6, TCP или SCTP).

optval — это указатель на переменную, из которой извлекается новое значение параметра с помощью функции setsockopt или в которой сохраняется текущее значение параметра с помощью функции getsockopt. Размер этой переменной задается последним аргументом. Для функции setsockopt тип этого аргумента — значение, а для функции getsockopt — «значение-результат».

В табл. 7.1 и 7.2 сведены параметры, которые могут запрашиваться функцией getsockopt или устанавливаться функцией setsockopt. В колонке «Тип данных» приводится тип данных того, на что указывает указатель optval для каждого параметра. Две фигурные скобки мы используем, чтобы обозначить структуру, например linger{} обозначает struct linger.

Таблица 7.1. Параметры сокетов для функций getsockopt и setsockopt

level optname get set Описание Флаг Тип данных SOL_SOCKET SO_BROADCAST • • Позволяет посылать широковещательные дейтаграммы • int SO_DEBUG • • Разрешает отладку • int SO_DONTROUTE • • Обходит таблицу маршрутизации • int SO_ERROR • Получает ошибку, ожидающую обработки, и возвращает значение параметра в исходное состояние int SO_KEEPALIVE • • Периодически проверяет, находится ли соединение в рабочем состоянии • int SO_LINGER • • Задерживает закрытие сокета, если имеются данные для отправки linger{} SO_OOBINLINE • • Оставляет полученные внеполосные данные вместе с обычными данными (inline) • int SO_RCVBUF • • Размер приемного буфера int SO_SNDBUF • • Размер буфера отправки int SO_RCVLOWAT • • Минимальное количество данных для приемного буфера сокета int SO_SNDLOWAT • • Минимальное количество данных для буфера отправки сокета int SO_RCVTIMEO • • Тайм-аут при получении timeval{} SO_SNDTIMEO • • Тайм-аут при отправке timeval{} SO_REUSEADDR • • Допускает повторное использование локального адреса • int SO_REUSEPORT • • Допускает повторное использование локального адреса • int SO_TYPE • Возвращает тип сокета int SO_USELOOPBACK • • Маршрутизирующий сокет получает копию того, что он отправляет • int IPPROTO_IP IP_HDRINCL • • Включается IP- заголовок • int IP_OPTIONS • • В заголовке IPv4 устанавливаются параметры IP см. текст IP_RECVDSTADDR • • Возвращает IP-адрес получателя • int IP_RECVIF • • Возвращает индекс интерфейса, на котором принимается дейтаграмма UDP • int IP_TOS • • Тип сервиса и приоритет int IP_TTL • • Время жизни int IP_MULTICAST_IF • • Задает интерфейс для исходящих дейтаграмм in_addr{} IP_MULTICAST_TTL • • Задает TTL для исходящих дейтаграмм u_char IP_MULTICAST_LOOP • • Разрешает или отменяет отправку копии дейтаграммы на тот узел, откуда она была послана (loopback) u_char IP_ADD_MEMBERSHIP • Включение в группу многоадресной передачи ip_mreq{} IP_DROP_MEMBERSHIP • Отключение от группы многоадресной передачи ip_mreq{} IP_{BLOCK, UNBLOCK}_SOURCE • Блокирование и разблокирование источника многоадресной передачи ip_mreq_source{} IP_{ADD, DROP}_SOURCE_MEMBERSHIP • Присоединение или отключение от многоадресной передачи от источника (source-specific) ip_mreq_source{} IPPROTO_ICMPV6 ICMP6_FILTER • • Указывает тип сообщения ICMPv6, которое передается процессу icmp6_filter{} IPPROTO_IPV6 IPV6_ADDRFORM • • Меняет формат адреса сокета int IPV6_CHECKSUM • • Отступ поля контрольной суммы для символьных (неструктурированных) сокетов int IPV6_DONTFRAG • • Не фрагментировать, а сбрасывать большие пакеты • int IPV6_NEXTHOP • • Задает следующий транзитный адрес • sockaddr{} IPV6_PATHMTU • Получение текущей маршрутной МТУ ip6_mtuinfo{} IPV6_RECVDSTOPTS • • Получение параметров адресата • int IPV6_RECVHOPLIMIT • • Получение ограничения на количество транзитных узлов при направленной передаче • int IPV6_RECVHOPOPTS • • Получение параметров прыжков • int IPV6_RECVPATHMTU • • Получение маршрутной MTU • int IPV6_RECVPKTINFO • • Получение информации о пакетах • int IPV6_RECVRTHDR • • Получение маршрута от источника • int IPV6_RECVTCLASS • • Получение класса трафика • int IPV6_UNICAST_HOPS • • Предел количества транзитных узлов, задаваемый по умолчанию int IPV6_USE_MIN_MTU • • Использовать минимальную MTU • int IPV6_V60NLY • • Отключить совместимость с IPv4 • int IPV6_XXX • • Вспомогательные данные см. текст IPV6_MULTICAST_IF • • Задает интерфейс для исходящих дейтаграмм u_int IPV6_MULTICAST_HOPS • • Задает предельное количество транзитных узлов для исходящих широковещательных сообщений int IPV6_MULTICAST_LOOP • • Разрешает или отменяет отправку копии дейтаграммы на тот узел, откуда она была послана (loopback) • u_int IPV6_LEAVE_GROUP • Выход из группы многоадресной передачи ipv6_mreq{} IPPROTO_IP или IPPROTO_IPV6 MCAST_JOIN_GROUP • Присоединение к группе многоадресной передачи group_req{} MCAST_LEAVE_GROUP • Выход из группы многоадресной передачи group_source_req{} MCAST_BLOCK_SOURCE • Блокирование источника многоадресной передачи group_source_req{} MCAST_UNBLOCK_SOURCE • Разблокирование источника многоадресной передачи group_source_req{} MCAST_JOIN_SOURCE_GROUP • Присоединение к группе многоадресной передачи от источника group_source_req{} MCAST_LEAVE_SOURCE_GROUP • Выход из группы многоадресной передачи от источника group_source_req{}

Перейти на страницу:
Изменить размер шрифта: