Если приложение не отслеживало изменения MTU при помощи параметра IPV6_RECVPATHMTU
, оно может определить текущее значение транспортной MTU IPV6_PATHMTU
. Этот параметр доступен только для чтения и возвращает он структуру ip6_mtuinfo
(см. выше), в которой хранится текущее значение MTU. Если значение еще не было определено, возвращается значение MTU по умолчанию для исходящего интерфейса. Значение адреса из структуры ip6_mtuinfo
в данном случае не определено.
Отключение фрагментации
По умолчанию стек IPv6 фрагментирует исходящие пакеты по транспортной MTU. Приложениям типа traceroute
автоматическая фрагментация не нужна, потому что им нужно иметь возможность самостоятельно определять транспортную MTU. Параметр сокета IPV6_DONTFRAG
используется для отключения автоматической фрагментации: значение 0 (по умолчанию) разрешает фрагментацию, тогда как значение 1 отключает ее.
Когда автоматическая фрагментация отключена, вызов send со слишком большим пакетом может возвратить ошибку EMSGSIZE
, но это не является обязательным. Единственным способом определить необходимость фрагментации пакета является использование параметра сокета IPV6_RECVPATHMTU
, который мы описали выше.
Параметр IPV6_DONTFRAG
может передаваться и во вспомогательных данных. При этом элемент cmsg_level
структуры cmsghdr
должен иметь значение IPPROTO_IPV6
, а элемент cmsg_type
должен иметь значение IPV6_DONTFRAG
. Первый байт данных должен быть первым байтом четырехбайтового целого.
22.10. Резюме
Существуют приложения, которым требуется знать IP-адрес получателя дейтаграммы UDP и интерфейс, на котором была получена эта дейтаграмма. Чтобы получать эту информацию в виде вспомогательных данных для каждой дейтаграммы, можно установить параметры сокета IP_RECVDSTADDR
и IP_RFCVIF
. Аналогичная информация вместе с предельным значением количества транзитных узлов полученной дейтаграммы для сокетов IPv6 становится доступна при включении параметра сокета IPV6_PKTINFO
.
Несмотря на множество полезных свойств, предоставляемых протоколом TCP и отсутствующих в UDP, существуют ситуации, когда следует отдать предпочтение UDP. UDP
В разделе 22.5 мы добавили нашему клиенту UDP определенные функциональные возможности, повышающие его надежность за счет обнаружения факта потери пакетов, для чего используются тайм-аут и повторная передача. Мы изменяли тайм-аут повторной передачи динамически, снабжая каждый пакет отметкой времени и отслеживая два параметра: период обращения RTT и его среднее отклонение. Мы также добавили порядковые номера, чтобы проверять, что данный ответ — это ожидаемый нами ответ на определенный запрос. Наш клиент продолжал использовать простой протокол остановки и ожидания (stop-and-wait), а приложения такого типа допускают применение UDP.
Упражнения
1. Почему в листинге 22.16 функция printf
вызывается дважды?
2. Может ли когда-нибудь функция dg_send_recv
(см. листинги 22.6 и 22.7) возвратить нуль?
3. Перепишите функцию dg_send_recv
с использованием функции select
и ее таймера вместо alarm
, SIGALRM
, sigsetjmp
и siglongjmp
.
4. Как может сервер IPv4 гарантировать, что адрес отправителя в его ответе совпадает с адресом получателя клиентского запроса? (Аналогичную функциональность предоставляет параметр сокета IPV6_PKTINFO
.)
5. Функция main
в разделе 22.6 является зависящей от протокола (IPv4). Перепишите ее, чтобы она стала не зависящей от протокола. Потребуйте, чтобы пользователь задал один или два аргумента командной строки, первый из которых — необязательный IP-адрес (например, 0.0.0.0 или 0::0), а второй — обязательный номер порта. Затем вызовите функцию udp_client
, чтобы получить семейство адресов, номер порта и длину структуры адреса сокета.
Что произойдет, если вы вызовете функцию udp_client
, как было предложено, не задавая аргумент hostname
, поскольку функция udp_client
не задает значение AI_PASSIVE
функции getaddrinfo
?
6. Соедините клиент, показанный в листинге 22.4, с эхо-сервером через Интернет, изменив функции rtt_
так, чтобы выводилось каждое значение RTT. Также измените функцию dg_send_recv
, чтобы она выводила каждый полученный порядковый номер. Изобразите на графике полученные в результате значения RTT вместе с оценочными значениями RTT и среднего отклонения.