UNIX: разработка сетевых приложений
UNIX: разработка сетевых приложений читать книгу онлайн
Новое издание книги, посвященной созданию веб-серверов, клиент-серверных приложений или любого другого сетевого программного обеспечения в операционной системе UNIX, — классическое руководство по сетевым программным интерфейсам, в частности сокетам. Оно основано на трудах Уильяма Стивенса и полностью переработано и обновлено двумя ведущими экспертами по сетевому программированию. В книгу включено описание ключевых современных стандартов, реализаций и методов, она содержит большое количество иллюстрирующих примеров и может использоваться как учебник по программированию в сетях, так и в качестве справочника для опытных программистов.
Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала
Листинг 20.6 демонстрирует использование канала внутри процесса. Обработчик сигналов записывает в канал 1 байт, когда истекает время таймера, а наша функция
dg_cliforselectЛистинг 20.6. Использование канала в качестве IPC между обработчиком сигнала и нашей функцией
//bcast/dgclibcast6.c 1 #include "unp.h" 2 static void recvfrom_alarm(int); 3 static int pipefd[2]; 4 void 5 dg_cli(FILE *fp, int sockfd, const SA *pservaddr, socklen_t servlen) 6 { 7 int n, maxfdp1; 8 const int on = 1; 9 char sendline[MAXLINE], recvline[MAXLINE + 1];10 fd_set rset;11 socklen_t len;12 struct sockaddr *preply_addr;13 preply_addr = Malloc(servlen);14 Setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on));15 Pipe(pipefd);16 maxfdp1 = max(sockfd, pipefd[0]) + 1;17 FD_ZERO(&rset);18 Signal(SIGALRM, recvfrom_alarm);19 while (Fgets(sendline, MAXLINE, fp) != NULL) {20 Sendto(sockfd, sendline, strlen(sendline), 0, pservaddr, servlen);21 alarm(5);22 for (;;) {23 FD_SET(sockfd, &rset);24 FD_SET(pipefd[0], &rset);25 if ((n = select(maxfdp1, &rset, NULL, NULL, NULL)) < 0) {26 if (errno == EINTR)27 continue;28 else29 err_sys("select error");30 }31 if (FD_ISSET(sockfd, &rset)) {32 len = servlen;33 n = Recvfrom(sockfd, recvline, MAXLINE, 0, preply_addr,34 &len);35 recvline[n] = 0; /* null terminate */36 printf("from %s: %s",37 Sock_ntop_host(preply_addr, len), recvline);38 }39 if (FD_ISSET(pipefd[0], &rset)) {40 Read(pipefd[0], &n, 1); /* истекшее время */41 break;42 }43 }44 }45 free(preply_addr);46 }47 static void48 recvfrom_alarm(int signo)49 {50 Write(pipefd[1], "", 1); /* в канал пишется один нулевой байт */51 return;52 }15pipefd[0]pipefd[0]Мы могли бы использовать функцию socketpair и получить двусторонний канал. В некоторых системах, особенно SVR4, обычный канал Unix всегда является двусторонним, и мы можем и читать, и записывать на любом конце этого канала.
23-30select47-52SIGALRMselectselectEINTRfor38-41breakfor20.6. Резюме
При широковещательной передаче посылается дейтаграмма, которую получают все узлы. Недостатком широковещательной передачи является то, что каждый узел в подсети должен обрабатывать дейтаграмму, вплоть до уровня UDP в случае дейтаграммы UDP, даже если на узле не выполняется приложение-адресат. Для приложений с большими потоками данных, таких как аудио- и видео-приложения, это может привести к повышенной нагрузке на все узлы. В следующей главе мы увидим, что многоадресная передача решает эту проблему, поскольку позволяет не получать дейтаграмму узлам, не заинтересованным в этом.
Использование версии нашего эхо-клиента UDP, который отправляет серверу времени и даты широковещательные дейтаграммы и затем выводит все его ответы, полученные в течение 5 с, позволяет нам рассмотреть ситуацию гонок, возникающую при применении сигнала
SIGALRMalarmSIGALRM
