20.4. Функция dg_cli при использовании широковещательной передачи
20.4. Функция dg_cli при использовании широковещательной передачи
Мы еще раз изменим нашу функцию dg_cli, на этот раз дав ей возможность отправлять широковещательные сообщения стандартному серверу времени и даты UDP (см. табл. 2.1) и выводить все ответы. Единственное изменение, внесенное нами в функцию main (см. листинг 8.3), состоит в изменении номера порта получателя на 13:
servaddr.sin_port = htons(13);
Сначала мы откомпилируем измененную функцию main с прежней функцией dg_cli из листинга 8.4 и запустим ее на узле freebsd:
freebsd % udpcli01 192.168.42.255
hi
sendto error: Permission denied
Аргумент командной строки — это широковещательный адрес подсети для присоединенной сети Ethernet. Мы вводим строку, программа вызывает функцию sendto, и возвращается ошибка EACCESS. Мы получаем ошибку, потому что нам не разрешается посылать дейтаграмму на широковещательный адрес получателя, если мы не указали ядру явно, что будем передавать широковещательное сообщение. Мы выполняем это условие, установив параметр сокета SO_BROADCAST (см. табл. 7.1).
ПРИМЕЧАНИЕ
Беркли-реализации реализуют эту «защиту от дурака» (sanity check). Однако Solaris 2.5 принимает дейтаграмму, предназначенную для широковещательного адреса, даже если мы не задаем параметр сокета SO_BROADCAST. Стандарт POSIX требует установки параметра сокета SO_BROADCAST для отправки широковещательной дейтаграммы.
В 4.2BSD широковещательная передача была привилегированной операцией, и параметра сокета SO_BROADCAST не существовало. В 4.3BSD этот параметр был добавлен и каждому процессу стало разрешено его устанавливать.
Теперь мы изменим нашу функцию dg_cli, как показано в листинге 20.1[1]. Эта версия устанавливает параметр сокета SO_BROADCAST и выводит все ответы, полученные в течение 5 с.
Листинг 20.1. Функция dg_cli, осуществляющая широковещательную передачу
//bcast/dgclibcast1.c
1 #include "unp.h"
2 static void recvfrom_alarm(int);
3 void
4 dg_cli(FILE *fp, int sockfd, const SA *pservaddr, socklen_t servlen)
5 {
6 int n;
7 const int on = 1;
8 char sendline[MAXLINE], recvline[MAXLINE + 1];
9 socklen_t len;
10 struct sockaddr *preply_addr;
11 preply_addr = Malloc(servlen);
12 Setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on));
13 Signal(SIGALRM, recvfrom_alarm);
14 while (Fgets(sendline, MAXLINE, fp) != NULL) {
15 Sendto(sockfd, sendline, strlen(sendline), 0, pservaddr, servlen);
16 alarm(5);
17 for (;;) {
18 len = servlen;
19 n = recvfrom(sockfd, recvline, MAXLINE, 0, preply_addr, &len);
20 if (n < 0) {
21 if (errno == EINTR)
22 break; /* окончание ожидания ответов */
23 else
24 err_sys("recvfrom error");
25 } else {
26 recvline[n] = 0; /* завершающий нуль */
27 printf("from %s: %s",
28 Sock_ntop_host(preply_addr, len), recvline);
29 }
30 }
31 }
32 free(preply_addr);
33 }
34 static void
35 recvfrom_alarm(int signo)
36 {
37 return; /* прерывание recvfrom() */
38 }
Выделение памяти для адреса сервера, установка параметра сокета
11-13 Функция malloc выделяет в памяти пространство для адреса сервера, возвращаемого функцией recvfrom. Устанавливается параметр сокета SO_BROADCAST, устанавливается обработчик сигнала SIGALRM.
Чтение строки, отправка сокету, чтение всех ответов
14-24 Следующие два вызова, fgets и sendto, выполняются так же, как и в предыдущих версиях этой функции. Но поскольку мы посылаем широковещательную дейтаграмму, мы можем получить множество ответов. Мы вызываем в цикле функцию recvfrom и выводим все ответы, полученные в течение 5 с. По истечении 5 с генерируется сигнал SIGALRM, вызывается наш обработчик сигнала и функция recvfrom возвращает ошибку EINTR.
Вывод каждого полученного ответа
25-29 Для каждого полученного ответа мы вызываем функцию sock_ntop_host, которая в случае IPv4 возвращает строку, содержащую IP-адрес сервера в точечно-десятичной записи. Эта строка выводится вместе с ответом сервера.
Если мы запустим программу, задав широковещательный адрес подсети 192. 168.42.255, мы увидим следующее:
bsdi % udpcli01 192.168.42.255 hi
from 192 168.42 2: Sat Aug 2 16.42.45 2003
from 192.168.42.1: Sat Aug 2 14.42.45 2003
from 192.168.42.3: Sat Aug 2 14.42.45 2003
hello
from 192.168.42.3: Sat Aug 2 14.42.57 2003
from 192.168.42.2: Sat Aug 2 16.42.57 2003
from 192.168.42.1: Sat Aug 2 14.42.57 2003
Каждый раз мы набираем строку ввода, чтобы сгенерировать выходную дейтаграмму UDP, и каждый раз получаем три ответа, причем отвечает и отправляющий узел. Как мы отмечали ранее, получателями широковещательной дейтаграммы являются все узлы в сети, включая отправляющий. Каждый ответ является направленным, поскольку адрес отправителя запроса, используемый каждым сервером в качестве адреса получателя ответа, — это адрес направленной передачи.
Все системы сообщают одно и то же время, поскольку на них используется NTP (Network Time Protocol — протокол синхронизации времени).
Более 800 000 книг и аудиокниг! 📚
Получи 2 месяца Литрес Подписки в подарок и наслаждайся неограниченным чтением
ПОЛУЧИТЬ ПОДАРОКДанный текст является ознакомительным фрагментом.
Читайте также
Проблемы при использовании
Проблемы при использовании Даже если положиться на то, что спрайты поддерживаются (почти) всеми браузерами на данный момент, все равно остается достаточно много вопросов, которые они не только не решают, а скорее сами создают. Во-первых, это проблемы при использовании
Отчет об использовании дискового пространства
Отчет об использовании дискового пространства Напишем сценарий DrivesReport.js, который будет создавать таблицу использования дискового пространства для дисков всех типов (съемных, жестких и сетевых), имеющихся на компьютере, в следующем формате: Диск: буква_диска Метка
8.6. Эхо-клиент UDP: функция dg_cli
8.6. Эхо-клиент UDP: функция dg_cli В листинге 8.4 показана функция dg_cli, которая выполняет большую часть работы на стороне клиента.Листинг 8.4. Функция dg_cli: цикл обработки клиента//lib/dg_cli.c 1 #include "unp.h" 2 void 3 dg_cli(FILE *fp, int sockfd, const SA *pservaddr, socklen_t servlen) 4 { 5 int n; 6 char sendline[MAXLINE], recvline[MAXLINE + 1]; 7
8.12. Функция dg_cli (продолжение)
8.12. Функция dg_cli (продолжение) Вернемся к функции dg_cli, показанной в листинге 8.4, и перепишем ее, с тем чтобы она вызывала функцию connect. В листинге 8.7 показана новая функция.Листинг 8.7. Функция dg_cli, вызывающая функцию connect//udpcliserv/dgcliconnect.c 1 #include "unp.h" 2 void 3 dg_cli(FILE *fp, int sockfd, const SA
21.3. Сравнение многоадресной и широковещательной передачи в локальной сети
21.3. Сравнение многоадресной и широковещательной передачи в локальной сети Вернемся к примерам, представленным на рис. 20.2 и 20.3, чтобы показать, что происходит в случае многоадресной передачи. В примере, показанном на рис. 21.3, мы будем использовать IPv4, хотя для IPv6
21.8 Функция dg_cli, использующая многоадресную передачу
21.8 Функция dg_cli, использующая многоадресную передачу Мы изменяем нашу функцию dg_cli, показанную в листинге 20.1, просто удаляя вызов функции setsockopt. Как мы сказали ранее, для отправки дейтаграмм многоадресной передачи не нужно устанавливать ни одного параметра сокета
Повышение уровня защиты при использовании CGI-сценариев
Повышение уровня защиты при использовании CGI-сценариев Если на Web-узле присутствуют CGI-сценарии, любой пользователь, работающий с Web-броузером, имеет возможность запустить на стороне сервера программу. Это может стать источником проблем, связанных с безопасностью
Вопросы защиты при использовании VPN
Вопросы защиты при использовании VPN Система VPN призвана повысить безопасность при обмене по сети. Однако она же может открыть злоумышленнику доступ к сетевым ресурсам. Взаимодействие компьютеров и сетей посредством VPN условно показано на рис. 26.1, 26.2 и 26.6. Однако из этих
Простота в использовании
Простота в использовании После правильной установки и настройки пользоваться системой VoIP-телефонии не сложнее, чем обычным телефоном. Принцип все тот же: вы снимаете трубку, ждете гудка, набираете номер, а когда собеседник отвечает, начинаете разговор. Конечно, если
2.1.9. Передача данных при использовании UDP
2.1.9. Передача данных при использовании UDP Мы наконец-то добрались до изучения того, ради чего сокеты и создавались: как передавать и получать с их помощью данные. По традиции начнем рассмотрение с более простого протокола UDP. Функции, которые рассматриваются в этом разделе,
2.1.11. Передача данных при использовании TCP
2.1.11. Передача данных при использовании TCP При программировании TCP и UDP применяются одни и те же функции, но их поведение при этом различно. Для передачи данных с помощью TCP необходимо сначала установить соединение, и после этого возможен обмен данными только с тем адресом, с
3.4.5. Ошибка EReadError при использовании вещественных свойств
3.4.5. Ошибка EReadError при использовании вещественных свойств Если в секции published компонента имеются свойства вещественного типа (Single, Double или Extended), то попытка присвоить в режиме проектирования формы этим свойствам некоторые вполне корректные значения приводит к ошибке
Советы об использовании текстовых полей
Советы об использовании текстовых полей Как основные элементы для отображения и ввода данных, текстовые поля заслуживают особого внимания, поэтому я рассматриваю их в настоящем разделе.Как и надписи, текстовые поля могут содержать сообщения, которые вы адресуете
Отсутствие поддержки ограничений при использовании операций
Отсутствие поддержки ограничений при использовании операций При создании обобщенных методов для вас может оказаться сюрпризом появление ошибок компилятора, когда с параметрами типа используются операции C# (+, -, *, == и т.д.). Например, я уверен, вы сочли бы полезными классы
Ошибка "объект находится в использовании"
Ошибка "объект находится в использовании" Исключение "object is in use" (объект находится в использовании) заслуживает внимания в контексте применения ограничений ссылочной целостности, поскольку является постоянным источником огорчений для новичков. Firebird не позволяет