KnigaRead.com/
KnigaRead.com » Компьютеры и Интернет » Программное обеспечение » Уильям Стивенс - UNIX: разработка сетевых приложений

Уильям Стивенс - UNIX: разработка сетевых приложений

На нашем сайте KnigaRead.com Вы можете абсолютно бесплатно читать книгу онлайн Уильям Стивенс, "UNIX: разработка сетевых приложений" бесплатно, без регистрации.
Перейти на страницу:

16  else

17   err_quit("usage: mysdr <mcast-addr> <port#> <interface-name>");


18  Setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));

19  Bind(sockfd, sa, salen);


20  Mcast_join(sockfd, sa, salen, (argc == 4) ? argv[3], NULL, 0);


21  loop(sockfd, salen); /* получение и вывод */


22  exit(0);

23 }

Заранее известные имя и порт

2-3 Адрес многоадресной передачи, заданный для анонсов SAP — 224.2.127.254, а его имя — sap.mcast.net. Все заранее известные адреса многоадресной передачи (см. http://www.iana.org/assignments/multicast-addresses) появляются в DNS в иерархии mcast.net. Заранее известный порт UDP — это порт 9875.

Создание сокета UDP

12-17 Мы вызываем нашу функцию udp_client, чтобы просмотреть имя и порт, и она заполняет соответствующую структуру адреса сокета. Если не заданы аргументы командной строки, мы используем значения по умолчанию. В противном случае мы получаем адрес многоадресной передачи, порт и имя интерфейса из аргументов командной строки.

Связывание порта с помощью функции 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(%sn", p);

40  }

41 }

Формат пакета

9-13 Структура sap_packet описывает пакет SDP: 32-разрядный заголовок SAP, за которым следует 32-разрядный адрес отправителя и сам анонс. Анонс представляет собой строки текста в стандарте ISO 8859-1 и не может превышать 1024 байта. В каждой дейтаграмме UDP допускается только один анонс сеанса.

Чтение дейтаграммы UDP, вывод параметров отправителя и содержимого

15-21 Функция recvfrom ждет следующую дейтаграмму UDP, предназначенную нашему сокету. Когда она приходит, мы помещаем в конец буфера пустой байт, исправляем порядок байтов заголовка и выводим адрес отправителя пакета и хэш SAP.

Проверка заголовка SAP

22-34 Мы проверяем заголовок SAP, чтобы убедиться, что он относится к одному из тех типов, с которыми мы умеем работать. Пакеты SAP с адресами IPv6 в заголовках, а также сжатые и зашифрованные пакеты мы не обрабатываем.

Поиск начала и вывод анонса

35-39 Мы пропускаем аутентифицирующие данные и тип пакета, после чего выводим содержимое оставшейся части.

В листинге 21.7 показано несколько типичных примеров результата выполнения нашей программы.

Листинг 21.7. Типичный анонс SAP/SDP

freebsd % mysdr

From 128.223.83.33:1028 hash 0x0000 v=0

o=- 60345 0 IN IP4 128.223.214.198

s=UO Broadcast - NASA Videos - 25 Years of Progress

i=25 Years of Progress, parts 1-13. Broadcast with Cisco System's

IP/TV using MPEG1 codec (6 hours 5 Minutes; repeats) More information

about IP/TV and the client needed to view this program is available

from http://videolab.uoregon.edu/download.html

u=http://videolab.uoregon.edu/

e=Hans Kuhn < [email protected]>

p=Hans Kuhn <541/346-1758>

b=AS:1000

t=0 0

a=type:broadcast

a=tool:IP/TV Content Manager 3.2.24

a=x-iptv-file:1 name y:25yop1234567890123.mpg

m=video 63096 RTP/AVP 32 31 96

c=IN IP4 224.2.245.25/127

a=framerate:30

a=rtpmap:96 WBIH/90000

a=x-iptv-svr:video blaster2.uoregon.edu file 1 loop

m=audio 31954 RTP/AVP 14 96 0 3 5 97 98 99 100 101 102 10 11 103 104 105 106

c=IN IP4 224.2.216.85/127

a=rtpmap:96 X-WAVE/8000

a=rtpmap:97 L8/8000/2

a=rtpmap:98 L8/8000

a=rtpmap:99 L8/22050/2

a=rtpmap:100 L8/22050

a=rtpmap:101 L8/11025/2

a=rtpmap:102 L8/11025

a=rtpmap:103 L16/22050/2

a=rtpmap:104 L16/22050

a=rtpmap:105 L16/11025/2

a=rtpmap:106 L16/11025

a=x-iptv-svr:audio blaster2.uoregon.edu file 1 loop

Этот анонс описывает рассылки, посвященные истории NASA (National Aeronautics and Space Administration — НАСА, государственная организация США, занимающаяся исследованием космоса). Описание сеанса SDP состоит из множества строк следующего формата:

type=value

где type всегда является одним символом, значение которого зависит от регистра, a value — это структурированная текстовая строка, зависящая от значения type. Пробелы справа и слева от знака равенства недопустимы. v=0 (в нашем случае) обозначает версию (version).

■ o= обозначает источник (origin). В данном случае имя пользователя не указано, 60345 — идентификатор сеанса, 0 — номер версии этого сеанса, IN — тип сети, IР4 — тип адреса, 128.223.214.198 — адрес. В результате объединения этих пяти элементов — имя пользователя, идентификатор сеанса, тип сети, тип адреса и адрес — образуется глобально уникальный идентификатор сеанса.

■ s= задает имя сеанса (session name), а i= — это информация о сеансе (information). u= указывает URI (Uniform Resource Identifier — уникальный идентификатор ресурса), по которому можно найти более подробную информацию по тематике данного сеанса, а р= и e= задают номер телефона (phone number) и адрес электронной почты (e-mail) ответственного за данную конференцию.

■ b= позволяет оценить пропускную способность, необходимую для приема данного сеанса.

■ t= задает время начала и время окончания сеанса в единицах NTP (Network Time Protocol — синхронизирующий сетевой протокол), то есть число секунд, прошедшее с 1 января 1900 года, измеренное в соответствии с UTC (Universal Time Coordinated — универсальное скоординированное время). Данный сеанс является постоянным и не имеет конкретных моментов начала и окончания, поэтому соответствующие времена полагаются нулевыми.

■ Строки a= представляют собой атрибуты, либо сеанса, если они помещены до первой строки m=, либо мультимедиа, если они помещены после первой строки m=.

■ Строки m= — это анонсы мультимедиа. Первая строка говорит нам о том, что видео передается на порт 63 096 в формате RTP с использованием профиля аудио и видео (Audio/Video Profile, AVP) с возможными типами данных 32, 31 и 96 (то есть MPEG, H.261 и WBIH соответственно). Строка c= сообщает о соединении. В данном случае используется протокол IPv4 с групповым адресом 224.2.245.25 и TTL = 127. Хотя между этими числами стоит символ «косая черта», как в формате CIDR, они ни в коем случае не должны трактоваться как префикс и маска.

Следующая строка m= говорит, что аудиопоток передается на порт 31 954 и может иметь один из типов RTP/AVP, некоторые из которых являются стандартными, в то время как другие указаны ниже в виде атрибутов a=rtpmap:. Строка с= сообщает нам сведения об аудиосоединении: IPv4 с групповым адресом 224.2.216.85 и TTL = 127.

21.10. Отправка и получение

Перейти на страницу:
Прокомментировать
Подтвердите что вы не робот:*