Измените реализацию функции mcast_set_if
для IPv4 так, чтобы запоминать имя каждого интерфейса, для которого она получает IP-адрес. Это позволит избежать нового вызова функции ioctl
для данного интерфейса.
Глава 22
Дополнительные сведения о сокетах udp
Эта глава объединяет различные темы, касающиеся приложений, использующих сокеты UDP. Для начала нас интересует, как определяется адрес получателя дейтаграммы UDP и интерфейс, на котором дейтаграмма была получена, поскольку сокет, связанный с портом UDP и универсальным адресом, может получать дейтаграммы направленной, широковещательной и многоадресной передачи на любом интерфейсе.
TCP — это потоковый протокол, использующий окно переменной величины ( sliding window ), поэтому в TCP отсутствует такое понятие, как граница записи, и невозможно переполнение буфера получателя отправителем в результате передачи слишком большого количества данных. Однако в случае UDP каждой операции ввода соответствует одна дейтаграмма UDP (запись), поэтому возникает вопрос: что произойдет, когда полученная дейтаграмма окажется больше приемного буфера приложения?
UDP — это ненадежный протокол, однако существуют приложения, в которых UDP использовать целесообразнее, чем TCP. Мы рассмотрим факторы, под влиянием которых UDP оказывается предпочтительнее TCP. В UDP-приложения необходимо включать ряд функций, в некоторой степени компенсирующих ненадежность UDP: тайм-аут и повторную передачу, обработку потерянных дейтаграмм и порядковые номера для сопоставления ответов запросам. Мы разработаем набор функций, которые сможем вызывать из наших приложений UDP.
Если реализация не поддерживает параметр сокета IP_RECVDSTADDR
, один из способов определить IP-адрес получателя UDP-дейтаграммы заключается в связывании всех интерфейсных адресов и использовании функции select
.
Большинство серверов UDP являются последовательными, но существуют приложения, обменивающиеся множеством дейтаграмм UDP между клиентом и сервером, что требует параллельной обработки. Примером может служить TFTP (Trivial File Transfer Protocol — упрощенный протокол передачи файлов). Мы рассмотрим два варианта подобного согласования — с использованием суперсервера inetd
и без него.
В завершение этой главы мы рассмотрим информацию о пакете, которая может быть передана во вспомогательных данных дейтаграммы IPv6: IP-адрес отправителя, отправляющий интерфейс, предельное количество транзитных узлов исходящих дейтаграмм и адрес следующего транзитного узла. Аналогичная информация — IP-адрес получателя, принимающий интерфейс и предельное количество транзитных узлов — может быть получена вместе с дейтаграммой IPv6.
22.2. Получение флагов, IP-адреса получателя и индекса интерфейса
Исторически функции sendmsg
и recvmsg
использовались только для передачи дескрипторов через доменные сокеты Unix (см. раздел 15.7), но даже это происходило сравнительно редко. Однако в настоящее время популярность этих двух функций растет по двум причинам:
1. Элемент msg_flags
, добавленный в структуру msghdr
в реализации 4.3BSD Reno, возвращает приложению флаги сообщения. Эти флаги мы перечислили в табл. 14.2.
2. Вспомогательные данные используются для передачи все большего количества информации между приложением и ядром. В главе 27 мы увидим, что IPv6 продолжает эту тенденцию.
В качестве примера использования функции recvmsg
мы напишем функцию recvfrom_flags
, аналогичную функции recvfrom, но дополнительно позволяющую получить:
■ возвращаемое значение msg_flags
;
■ адрес получателя полученной дейтаграммы (из параметра сокета IP_RECVDSTADDR
);
■ индекс интерфейса, на котором была получена дейтаграмма (параметр сокета IP_RECVIF
).
Чтобы можно было получить два последних элемента, мы определяем в нашем заголовке unp.h
следующую структуру:
struct in_pktinfo {
struct in_addr ipi_addr; /* IPv4-адрес получателя */
int ipi_ifindex; /* индекс интерфейса, на котором была
получена дейтаграмма */
};
Мы выбрали имена структуры и ее элементов так, чтобы получить определенное сходство со структурой IPv6 in6_pktinfo
, возвращающей те же два элемента для сокета IPv6 (см. раздел 22.8). Наша функция recvfrom_flags
будет получать в качестве аргумента указатель на структуру in_pktinfo
, и если этот указатель не нулевой, возвращать структуру через указатель.
Читать дальше
Конец ознакомительного отрывка
Купить книгу