UNIX: разработка сетевых приложений
UNIX: разработка сетевых приложений читать книгу онлайн
Новое издание книги, посвященной созданию веб-серверов, клиент-серверных приложений или любого другого сетевого программного обеспечения в операционной системе UNIX, — классическое руководство по сетевым программным интерфейсам, в частности сокетам. Оно основано на трудах Уильяма Стивенса и полностью переработано и обновлено двумя ведущими экспертами по сетевому программированию. В книгу включено описание ключевых современных стандартов, реализаций и методов, она содержит большое количество иллюстрирующих примеров и может использоваться как учебник по программированию в сетях, так и в качестве справочника для опытных программистов.
Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала
Листинг 20.4. Простая некорректная реализация функции pselect
//lib/pselect.c 9 #include "unp.h"10 int11 pselect(int nfds, fd_set *rset, fd_set *wset, fd_set *xset,12 const struct timespec *ts, const sigset_t *sigmask)13 {14 int n;15 struct timeval tv;16 sigset_t savemask;17 if (ts != NULL) {18 tv.tv_sec = ts->tv_sec;19 tv.tv_usec = ts->tv_nsec / 1000; /* наносекунды -> микросекунды */20 }21 sigprocmask(SIG_SETMASK, sigmask, &savemask); /* маска вызывающего процесса */22 n = select(nfds, rset, wset, xset., (ts == NULL) ? NULL : &tv);23 sigprocmask(SIG_SETMASK, &savemask, NULL); /* восстанавливаем исходную маску */24 return (n);25 }Использование функций sigsetjmp и siglongjmp
Нашу проблему можно решить корректно, если отказаться от прерывания блокированного системного вызова обработчиком сигнала, вместо этого вызвав из обработчика сигнала функцию
siglongjmpЛистинг 20.5. Вызов функций sigsetjmp и siglongjmp из обработчика сигнала
//bcast/dgclibcast5.c 1 #include "unp.h" 2 #include <setjmp.h> 3 static void recvfrom_alarm(int); 4 static sigjmp_buf jmpbuf; 5 void 6 dg_cli(FILE *fp, int sockfd, const SA *pservaddr, socklen_t servlen) 7 { 8 int n; 9 const int on = 1;10 char sendline[MAXLINE], recvline[MAXLINE + 1];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 Signal(SIGALRM, recvfrom_alarm);16 while (Fgets(sendline, MAXLINE, fp) != NULL) {17 Sendto(sockfd, sendline, strlen(sendline), 0, pservaddr, servlen);18 alarm(5);19 for (;;) {20 if (sigsetjmp(jmpbuf, 1) != 0)21 break;22 len = servlen;23 n = Recvfrom(sockfd, recvline, MAXLINE, 0, preply_addr, &len);24 recvline[n] = 0; /* null terminate */25 printf("from %s: %s",26 Sock_ntop_host(preply_addr, len), recvline);27 }28 }29 free(preply_addr);30 }31 static void32 recvfrom_alarm(int signo)33 {34 siglongjmp(jmpbuf, 1);35 }420-23sigsetjmpdg_clirecvfrom31-35siglongjmpsigsetjmpdg_clifordg_cliИспользование функций
sigsetjmpsiglongjmprecvfromprintfprintfsigsetjmpprintfgotoПрименение IPC в обработчике сигнала функции
Существует еще один корректный путь решения нашей проблемы. Вместо того чтобы просто возвращать управление и, как мы надеемся, прерывать блокированную функцию
recvfromdg_clihad_alarm
