Шрифт:
Связывание порта с помощью функции bind
18-19
Мы устанавливаем параметр сокета SO_REUSEADDR
, чтобы позволить множеству экземпляров этой программы запуститься на узле, и с помощью функции bind связываем порт с сокетом. Связывая адрес многоадресной передачи с сокетом, мы запрещаем сокету получать какие-либо другие дейтаграммы UDP, которые могут быть получены для этого порта. Связывание этого адреса многоадресной передачи не является обязательным, но оно обеспечивает возможность фильтрации, благодаря чему ядро может не принимать пакеты, которые его не интересуют. Присоединение к группе
20
Мы вызываем нашу функцию mcast_join
, чтобы присоединиться к группе. Если имя интерфейса было задано в качестве аргумента командной строки, оно передается нашей функции, иначе мы позволяем ядру выбрать интерфейс, на котором будет происходить присоединение к группе.
21
Мы вызываем нашу функцию loop
, показанную в листинге 21.6, чтобы прочитать и вывести все анонсы. Листинг 21.6. Цикл, получающий и выводящий анонсы SAP/SDP
//mysdr/loop.c
1 #include "mysdr.h"
2 void
3 loop(int sockfd, socklen_t salen)
4 {
5 socklen_t len;
6 ssize_t n;
7 char *p;
8 struct sockaddr *sa;
9 struct sap_packet {
10 uint32_t sap_header;
11 uint32_t sap_src;
12 char sap_data[BUFFSIZE];
13 } buf;
14 sa = Malloc(salen);
15 for (;;) {
15 len = salen;
17 n = Recvfrom(sockfd, &buf, sizeof(buf) - 1, 0, sa, &len);
18 ((char *)&buf)[n] = 0; /* завершающий нуль */
19 buf.sap_header = ntohl(buf.sap_header);
20 printf("From %s hash 0х%0х\n" Sock_ntop(sa, len),
21 buf.sap_header & SAP_HASH_MASK);
22 if (((buf.sap_header & SAP_VERSION_MASK) >> SAP_VERSION_SHIFT) > 1) {
23 err_msg("... version field not 1 (0x%08x)", buf.sap_header);
24 continue;
25 }
26 if (buf.sap_header & SAP_IPV6) {
27 err_msg("... IPv6");
28 continue;
29 }
30 if (buf.sap_header & (SAP_DELETE|SAP_ENCRYPTED|SAP_COMPRESSED)) {
31 err_msg("... can't parse this packet type (0x%80x)",
32 buf.sap_header);
33 continue;
34 }
35 p = buf.sap_data + ((buf.sap_header & SAP AUTHLEN_MASK)
36 >> SAP_AUTHLEN_SHIFT);
37 if (strcmp(p.,"application/sdp") == 0)
38 p += 16;
39 printf(%s\n", p);
40 }
41 }
Формат пакета
9-13
Структура sap_packet
описывает пакет SDP: 32-разрядный заголовок SAP, за которым следует 32-разрядный адрес отправителя и сам анонс. Анонс представляет собой строки текста в стандарте ISO 8859-1 и не может превышать 1024 байта. В каждой дейтаграмме UDP допускается только один анонс сеанса. Чтение дейтаграммы UDP, вывод параметров отправителя и содержимого