struct ip6_mtuinfo {
struct sockaddr_in6 ip6m_addr; /* адрес узла */
uint32_t ip6m_mtu; /* транспортная MTU
в порядке байтов узла */
};
Эта структура определяется включением заголовочного файла .
Определение текущей транспортной MTU
Если приложение не отслеживало изменения 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
. Первый байт данных должен быть первым байтом четырехбайтового целого.
Существуют приложения, которым требуется знать IP-адрес получателя дейтаграммы UDP и интерфейс, на котором была получена эта дейтаграмма. Чтобы получать эту информацию в виде вспомогательных данных для каждой дейтаграммы, можно установить параметры сокета IP_RECVDSTADDR
и IP_RFCVIF
. Аналогичная информация вместе с предельным значением количества транзитных узлов полученной дейтаграммы для сокетов IPv6 становится доступна при включении параметра сокета IPV6_PKTINFO
.
Несмотря на множество полезных свойств, предоставляемых протоколом TCP и отсутствующих в UDP, существуют ситуации, когда следует отдать предпочтение UDP. UDP должен использоваться для широковещательной или многоадресной передачи. 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
, чтобы получить семейство адресов, номер порта и длину структуры адреса сокета.
Читать дальше
Конец ознакомительного отрывка
Купить книгу