UNIX: разработка сетевых приложений
UNIX: разработка сетевых приложений читать книгу онлайн
Новое издание книги, посвященной созданию веб-серверов, клиент-серверных приложений или любого другого сетевого программного обеспечения в операционной системе UNIX, — классическое руководство по сетевым программным интерфейсам, в частности сокетам. Оно основано на трудах Уильяма Стивенса и полностью переработано и обновлено двумя ведущими экспертами по сетевому программированию. В книгу включено описание ключевых современных стандартов, реализаций и методов, она содержит большое количество иллюстрирующих примеров и может использоваться как учебник по программированию в сетях, так и в качестве справочника для опытных программистов.
Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала
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
SIGALRM
recvfrom
EINTR
25-29
sock_ntop_host
Если мы запустим программу, задав широковещательный адрес подсети 192. 168.42.255, мы увидим следующее:
bsdi % <b>udpcli01 192.168.42.255 hi</b>
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
<b>hello</b>
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 — протокол синхронизации времени).
Фрагментация IP-пакетов и широковещательная передача
В Беркли-ядрах фрагментация широковещательных дейтаграмм запрещена. Если размер IP-дейтаграммы, посылаемой на широковещательный адрес, превышает размер MTU исходящего интерфейса, возвращается ошибка
EMSGSIZE
Можно наблюдать этот сценарий с нашей программой из листинга 20.1. Мы перенаправляем стандартный поток ввода для чтения из файла, содержащего 2000-байтовую строку, которая потребует фрагментации в Ethernet:
bsdi % <b>udpcli01 192.168.42.255 < 2000line</b>
sendto error: Message too long
Это ограничение реализовано в AIX, FreeBSD и MacOS. Linux, Solaris и HP-UX фрагментируют дейтаграммы, отправленные на широковещательный адрес. Однако в целях переносимости приложение, которому нужно сделать широковещательный запрос, должно определять MTU для интерфейса, через который будет отправлено сообщение, при помощи параметра SIOCGIPMTU функции ioctl, после чего вычесть размер заголовков IP и транспортного протокола. Альтернативный подход: выбрать типичное значение MTU (например, 1500 для Ethernet) и использовать его в качестве константы.
20.5. Ситуация гонок
Ситуация гонок (race condition) обычно возникает, когда множество процессов получают доступ к общим для них данным, но корректность результата зависит от порядка выполнения процессов. Поскольку порядок выполнения процессов в типичных системах Unix зависит от множества факторов, которые могут меняться от запуска к запуску, иногда результат корректен, а иногда — нет. Наиболее сложным для отладки типом гонок является такой, когда результат получается некорректным только изредка. Более подробно о ситуациях гонок мы поговорим в главе 26, когда будем обсуждать взаимные исключения (mutex) и условные переменные (condition variables). При программировании потоков всегда возникают проблемы с ситуациями гонок, поскольку значительное количество данных является общим для всех потоков (например, все глобальные переменные).
Ситуации гонок другого типа часто возникают при работе с сигналами. Проблемы возникают, потому что сигнал, как правило, может быть доставлен в любой момент во время выполнения нашей программы. POSIX позволяет нам блокировать доставку сигнала, но при выполнении операций ввода-вывода это часто не дает эффекта.
Чтобы понять эту проблему, рассмотрим пример. Ситуация гонок возникает при выполнении программы из листинга 20.1. Потратьте несколько минут и посмотрите, сможете ли вы ее обнаружить. (Подсказка: в каком месте программы мы можем находиться, когда доставляется сигнал?) Вы можете также инициировать ситуацию гонок следующим образом: изменить аргумент функции
alarm
sleep(1)
printf