■ 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. Отправка и получение
Программа для получения анонсов сеанса многоадресной передачи, показанная в предыдущем разделе, могла только получать дейтаграммы многоадресной передачи. Теперь мы создадим простую программу, способную и отправлять, и получать дейтаграммы многоадресной передачи. Наша программа состоит из двух частей. Первая часть отправляет дейтаграмму многоадресной передачи определённой группе каждые 5 с. Эта дейтаграмма содержит имя узла отправителя и идентификатор процесса. Вторая часть программы — это бесконечный цикл, присоединяющийся к той группе, которой первая часть программы отправляет данные. В этом цикле выводится каждая полученная дейтаграмма (содержащая имя узла и идентификатор процесса отправителя). Это позволяет нам запустить программу на множестве узлов в локальной сети и посмотреть, какой узел получает дейтаграммы от каких отправителей.
В листинге 21.8 показана функция main
нашей программы.
Листинг 21.8. Создание сокетов, вызов функции fork и запуск отправителя и получателя
//mcast/main.c
1 #include "unp.h"
2 void recv_all(int, socklen_t);
3 void send_all(int. SA *, socklen_t);
4 int
5 main(int argc, char **argv)
6 {
7 int sendfd, recvfd;
8 const int on = 1;
9 socklen_t salen;
10 struct sockaddr *sasend, *sarecv;
11 if (argc != 3)
12 err_quit("usage: sendrecv
13 sendfd = Udp_client(argv[1], argv[2], (void**)&sasend, &salen);
14 recvfd = Socket(sasend->sa_family, SOCK_DGRAM, 0);
15 Setsockopt(recvfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
16 sarecv = Malloc(salen);
17 memcpy(sarecv, sasend, salen);
18 Bind(recvfd, sarecv, salen);
19 Mcast_join(recvfd, sasend, salen, NULL, 0);
20 Mcast_set_loop(sendfd, 0);
21 if (Fork() == 0)
22 recv_all(recvfd, salen); /* дочерний процесс -> получение */
23 send_all(sendfd, sasend, salen); /* родитель -> отправка */
24 }