Шрифт:
60 } else if (ifname != NULL) {
61 if ((mreq6.ipv6mr_interface = if_nametoindex(ifname)) == 0) {
62 errno = ENXIO; /* интерфейс не найден */
63 return(-1);
64 }
65 } else
66 mreq6.ipv6mr_interface = 0;
67 return(setsockopt(sockfd, IPPROTO_IPV6, IPV6_JOIN_GROUP,
68 &mreq6, sizeof(mreq6)));
69 }
70 #endif
71 default:
72 errno = EAFNOSUPPORT;
73 return(-1);
74 }
75 #endif
76 }
Копирование адреса
55-57
Сначала адрес IPv6 копируется из структуры адреса сокета в структуру ipv6_mreq
. Обработка индекса или имени интерфейса или выбор интерфейса по умолчанию
58-66
Если был задан индекс, он записывается в элемент ipv6mr_interface
. Если индекс не задан, но задано имя, то для получения индекса вызывается функция if_nametoindex
. В противном случае для функции setsockopt
индекс устанавливается в 0, что указывает ядру на необходимость выбрать интерфейс.
67-68
Выполняется присоединение к группе. Пример: функция mcast_set_loop
В листинге 21.4 показана наша функция
mcast_set_loop
. Поскольку аргументом является дескриптор сокета, а не структура адреса сокета, мы вызываем нашу функцию
sockfd_to_family
, чтобы получить семейство адресов сокета. Устанавливается соответствующий параметр сокета. Мы не показываем исходный код для всех остальных функций
mcast_ XXX
, так как он свободно доступен в Интернете (см. предисловие). Листинг 21.4. Установка параметра закольцовки для многоадресной передачи
//lib/mcast_set_loop.c
1 #include "unp.h"
2 int
3 mcast_set_loop(int sockfd, int onoff)
4 {
5 switch (sockfd_to_family(sockfd)) {
6 case AF_INET:{
7 u_char flag;
8 flag = onoff;
9 return (setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_LOOP,
10 &flag, sizeof(flag)));
11 }
12 #ifdef IPV6
13 case AF_INET6:{
14 u_int flag;
15 flag = onoff;
16 return (setsockopt(sockfd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
17 &flag, sizeof(flag)));
18 }
19 #endif
20 default:
21 errno = EPROTONOSUPPORT;
22 return (-1);
23 }
24 }
21.8 Функция dg_cli, использующая многоадресную передачу
Мы изменяем нашу функцию
dg_cli
, показанную в листинге 20.1, просто удаляя вызов функции setsockopt
. Как мы сказали ранее, для отправки дейтаграмм многоадресной передачи не нужно устанавливать ни одного параметра сокета многоадресной передачи, если нас устраивают заданные по умолчанию настройки интерфейса исходящих пакетов, значения TTL и параметра закольцовки. Мы запускаем нашу программу, задавая в качестве адреса получателя группу всех узлов (all-hosts group):
macosx % udpcli01 224.0.1.1
hi there
from 172.24.37.78: hi there MacOS X
from 172.24.37.94: hi there FreeBSD
Отвечают оба узла, находящиеся в подсети. На обоих работают многоадресные эхо-серверы. Каждый ответ является направленным, поскольку адрес отправителя запроса, используемый сервером в качестве адреса получателя ответа, является адресом направленной передачи.