3. Описывая рис. 2.15, мы отметили, что TCP считает MSS равным 536, если не получает величину параметра MSS от собеседника. Почему используется это значение?
4. Нарисуйте рисунок, аналогичный рис. 2.5, для клиент-серверного приложения времени и даты из главы 1, предполагая, что сервер возвращает 26 байт данных в отдельном сегменте TCP.
5. Допустим, что установлено соединение между узлом в Ethernet, чей TCP объявляет MSS, равный 1460, и узлом в Token-ring, чей TCP объявляет MSS, равный 4096. Ни один из узлов не пытается обнаружить, чему равна транспортная MTU. При просмотре пакетов мы никогда не видим более 1460 байт данных в любом направлении. Почему?
6. Описывая табл. 2.2, мы отметили, что OSPF использует IP непосредственно. Каково значение поля протокола в заголовке IPv4 (см. рис. А.1) для дейтаграмм OSPF?
7. Обсуждая отправку данных по SCRIPT, мы отметили, что отправителю приходится ждать получения кумулятивного уведомления, чтобы удалить данные из буфера сокета. Если еще до получения кумулятивного уведомления принято выборочное уведомление, указывающее, что данные уже доставлены, почему буфер все равно не может быть освобожден?
Часть 2
Элементарные сокеты
Глава 3
Введение в сокеты
3.1. Введение
Эта глава начинается с описания программного интерфейса приложения (API) сокетов. Мы начнем со структур адресов сокетов, которые будут встречаться почти в каждом примере на протяжении всей книги. Эти структуры можно передавать в двух направлениях: от процесса к ядру и от ядра к процессу. Последний случай — пример аргумента, через который передается возвращаемое значение, и далее в книге мы встретимся с другими примерами таких аргументов.
Перевод текстового представления адреса в двоичное значение, входящее в структуру адреса сокета, осуществляется функциями преобразования адресов. В большей части существующего кода IPv4 используются функции
inet_addr
и
inet_ntoa
, но две новых функции
inet_pton
и
inet_ntop
работают и с IPv4, и с IPv6.
Одной из проблем этих функций является то, что они зависят от протокола, так как для них имеет значение тип преобразуемого адреса — IPv4 или IPv6. Мы разработали набор функций, названия которых начинаются с
sock_
, работающих со структурами адресов сокетов независимо от протокола. Эти функции мы и будем использовать, чтобы сделать наш код не зависящим от протокола.
3.2. Структуры адреса сокетов
Большинство функций сокетов используют в качестве аргумента указатель на структуру адреса сокета. Каждый набор протоколов определяет свою собственную структуру адреса сокетов. Имена этих структур начинаются с
sockaddr_
и заканчиваются уникальным суффиксом для каждого набора протоколов.
Структура адреса сокета IPv4
Структура адреса сокета IPv4, обычно называемая структурой адреса сокета Интернета, именуется
sockaddr_in
и определяется в заголовочном файле
. В листинге 3.1
[1]представлено определение POSIX.
Листинг 3.1. Структура адреса сокета Интернета (IPv4): sockaddr_in
struct in_addr {
in_addr_t s_addr; /* 32-разрядный адрес IPv4 */
/* сетевой порядок байтов */
};
struct sockaddr_in {
uint8_t sin_len; /* длина структуры (16) */
sa_family_t sin_family; /* AF_INET */
in_port_t sin_port; /* 16-разрядный номер порта TCP или UDP */
/* сетевой порядок байтов */
struct in_addr sin_addr; /* 32-разрядный адрес IPv4 */
/* сетевой порядок байтов */
char sin_zero[8]; /* не используется */
};
Есть несколько моментов, касающихся структур адреса сокета в целом, которые мы покажем на примере.
Элемент длины
sin_len
появился в версии 4.3BSD-Reno, когда была добавлена поддержка протоколов OSI (см. рис. 1.6). До этой реализации первым элементом был
sin_family
, который исторически имел тип
unsigned short
(целое без знака). Не все производители поддерживают поле длины для структур адреса сокета, и в POSIX, например, не требуется наличия этого элемента. Типы данных, подобные
uint8_t
, введены в POSIX (см. табл. 3.1). Наличие поля длины упрощает обработку структур адреса сокета с переменной длиной.
Даже если поле длины присутствует, нам не придется устанавливать и проверять его значение, пока мы не имеем дела с маршрутизирующими сокетами (см. главу 18). Оно используется внутри ядра процедурами, работающими со структурами адресов сокетов из различных семейств протоколов (например, код таблицы маршрутизации).