KnigaRead.com/
KnigaRead.com » Компьютеры и Интернет » Программное обеспечение » Уильям Стивенс - UNIX: разработка сетевых приложений

Уильям Стивенс - UNIX: разработка сетевых приложений

На нашем сайте KnigaRead.com Вы можете абсолютно бесплатно читать книгу онлайн Уильям Стивенс, "UNIX: разработка сетевых приложений" бесплатно, без регистрации.
Перейти на страницу:

93  exit(0);

94 }

Перебор всех параметров

59-63 Мы перебираем все элементы нашего массива. Если указатель opt_val_str пустой, то параметр не определен реализацией (что, как мы показали, возможно для SO_REUSEPORT).

Создание сокета

63-82 Мы создаем сокет, на котором проверяем действие параметров. Для проверки параметров сокета и уровней IPv4 и TCP мы используем сокет IPv4 TCP. Для проверки параметров сокетов уровня IPv6 мы используем сокет IPv6 TCP, а для проверки параметров SCTP — сокет IPv4 SCTP.

Вызов функции getsockopt

83-87 Мы вызываем функцию getsockopt, но не завершаем ее выполнение, если возвращается ошибка. Многие реализации определяют имена некоторых параметров сокетов, даже если не поддерживают эти параметры. Неподдерживаемые параметры выдают ошибку ENOPROTOOPT.

Вывод значения параметра по умолчанию

88-89 Если функция getsockopt успешно завершается, мы вызываем нашу функцию для преобразования значения параметра в строку и выводим эту строку.

В листинге 7.1 мы показали четыре прототипа функций, по одному для каждого типа возвращаемого значения параметра. В листинге 7.3 показана одна из этих функций, sock_str_flag, которая выводит значение параметра, являющегося флагом. Другие три функции аналогичны этой.

Листинг 7.3. Функция sock_str_flag: преобразование флага в строку

//sockopt/checkopts.с

 95 static char strres[128];


 96 static char *

 97 sock_str_flag(union val *ptr, int len)

 98 {

 99  if (len != sizeof(int))

100   snprint(strres, sizeof(strres), "size (%d) not sizeof(int)", len);

101  else

102   snprintf(strres, sizeof(strres),

103    "%s", (ptr->i_val == 0) ? "off" : "on");

104  return(strres);

105 }

99-104 Вспомните, что последний аргумент функции getsockopt — это аргумент типа «значение-результат». Первое, что мы проверяем, — это то, что размер значения, возвращаемого функцией getsockopt, совпадает с предполагаемым. В зависимости от того, является ли значение флага нулевым или нет, возвращается строка off или on.

Выполнение этой программы под FreeBSD 4.8 с пакетами обновлений KAME SCTP дает следующий вывод:

freebsd % checkopts

SO_BROADCAST: default = off

SO_DEBUG: default = off

SO_DONTROUTE: default = off

SO_ERROR: default = 0

SO_KEEPALIVE: default = off

SO_LINGER: default = l_onoff = 0, l_linger = 0

SO_OOBINLINE: default = off

SO_RCVBUF: default = 57344

SO_SNDBUF: default = 32768

SO_RCVLOWAT: default = 1

SO_SNDLOWAT: default = 2048

SO_RCVTIMEO: default = 0 sec, 0 usec

SO_SNDTIMEO: default = 0 sec, 0 usec

SO_REUSEADDR: default = off

SO_REUSEPORT: default = off

SO_TYPE: default = 1

SO_USELOOPBACK: default = off

IP_TOS: default = 0

IP_TTL: default = 64

IPV6_DONTFRAG: default = off

IPV6_UNICAST_HOPS: default = -1

IPV6_V6ONLY: default = off

TCP_MAXSEG: default = 512

TCP_NODELAY: default = off

SCTP_AUTOCLOSE: default = 0

SCTP_MAXBURST: default = 4

SCTP_MAXSEG: default = 1408

SCTP_NODELAY: default = off

Значение 1, возвращаемое для параметра SO_TYPE, для этой реализации соответствует SOCK_STREAM.

7.4. Состояния сокетов

Для некоторых параметров сокетов время их установки или получения зависит некоторым образом от состояния сокета. Далее мы обсудим эту зависимость для тех параметров, к которым это относится.

Следующие параметры сокетов наследуются присоединенным сокетом TCP от прослушиваемого сокета [128, с. 462-463]: SO_DEBUG, SO_DONTROUTE, SO_KEEPALIVE, SO_LINGER, SO_OOBINLINE, SO_RCVBUF, SO_RCVLOWAT, SO_SNDBUF, SO_SNDLOWAT, TCP_MAXSEG и TCP_NODELAY. Это важно для TCP, поскольку присоединенный сокет не возвращается серверу функцией accept, пока трехэтапное рукопожатие не завершится на уровне TCP. Если при завершении трехэтапного рукопожатия мы хотим убедиться, что один из этих параметров установлен для присоединенного сокета, нам следует установить этот параметр еще для прослушиваемого сокета.

7.5. Общие параметры сокетов

Мы начнем с обсуждения общих параметров сокетов. Эти параметры не зависят от протокола (то есть они управляются не зависящим от протокола кодом внутри ядра, а не отдельным модулем протокола, такого как IPv4), но некоторые из них применяются только к определенным типам сокетов. Например, несмотря на то что параметр сокета SO_BROADCAST называется общим, он применяется только к дейтаграммным сокетам.

Параметр сокета SO_BROADCAST

Этот параметр управляет возможностью отправки широковещательных сообщений. Широковещательная передача поддерживается только для сокетов дейтаграмм и только в сетях, поддерживающих концепцию широковещательных сообщений (Ethernet, Token Ring и т.д.). Широковещательная передача в сетях типа «точка-точка» или по ориентированному на установление соединения транспортному протоколу типа SCTP или TCP, неосуществима. Более подробно о широковещательной передаче мы поговорим в главе 18.

Поскольку перед отправкой широковещательной дейтаграммы приложение должно установить этот параметр сокета, оно не сможет отправить широковещательное сообщение, если это не предполагалось заранее. Например, приложение UDP может принять IP-адрес получателя в качестве аргумента командной строки, но оно может и не предполагать, что пользователь вводит широковещательный адрес. Проверку того, является ли данный адрес широковещательным, осуществляет не приложение, а ядро: если адрес получателя является широковещательным адресом и данный параметр сокета не установлен, возвратится ошибка EACCESS [128, с. 233].

Параметр сокета SO_DEBUG

Этот параметр поддерживается только протоколом TCP. При подключении к сокету TCP ядро отслеживает подробную информацию обо всех пакетах, отправленных или полученных протоколом TCP для сокета. Они хранятся в кольцевом буфере внутри ядра, который можно проверить с помощью программы trpt. В [128, с. 916-920] приводится более подробная информация и пример использования этого параметра.

Параметр сокета SO_DONTROUTE

Этот параметр указывает, что исходящие пакеты должны миновать обычные механизмы маршрутизации соответствующего протокола. Например, в IPv4 пакет направляется на соответствующий локальный интерфейс, который задается адресом получателя, а именно сетевым адресом и маской подсети. Если локальный интерфейс не может быть определен по адресу получателя (например, получателем не является другой конец соединения типа «точка-точка» или он не находится в той же сети), возвращается ошибка ENETUNREACH.

Эквивалент этого параметра можно также применять к индивидуальным дейтаграммам, используя флаг MSG_DONTROUTE с функциями send, sendto или sendmsg.

Этот параметр часто используется демонами маршрутизации (routed и gated) для того, чтобы миновать таблицу маршрутизации (в случае, если таблица маршрутизации неверна) и заставить пакет отправиться на определенный интерфейс.

Параметр сокета SO_ERROR

Когда на сокете происходит ошибка, модуль протокола в ядре, происходящем от Беркли, присваивает переменной so_error для этого сокета одно из стандартных значений Unix Exxx. Это так называемая ошибка, требующая обработки (pending error) для данного сокета. Процесс может быть немедленно оповещен об ошибке одним из двух способов:

1. Если процесс блокируется в вызове функции select (см. раздел 6.3), ожидая готовности данного сокета к чтению или записи, функция select возвращает управление и уведомляет процесс о соответствующем состоянии готовности.

2. Если процесс использует управляемый сигналом ввод-вывод (см. главу 25), для него или для группы таких процессов генерируется сигнал SIGIO.

Процесс может получить значение переменной so_error, указав параметр сокета SO_ERROR. Целое значение, возвращаемое функцией getsockopt, является кодом ошибки, требующей обработки. Затем значение переменной so_error сбрасывается ядром в 0 [128, с. 547].

Если процесс вызывает функцию read и возвращаемых данных нет, а значение so_error ненулевое, то функция read возвращает -1 с errno, которой присвоено значение переменной so_error [128, с. 516]. Это значение so_error затем сбрасывается в 0. Если в очереди для сокета есть данные, эти данные возвращаются функцией read вместо кода ошибки. Если значение so_error ненулевое, то при вызове процессом функции write возвращается -1 с errno, равной значению переменной so_error [128, с. 495], а значение so_error сбрасывается в 0.

Перейти на страницу:
Прокомментировать
Подтвердите что вы не робот:*