Уильям Стивенс - UNIX: разработка сетевых приложений

Тут можно читать онлайн Уильям Стивенс - UNIX: разработка сетевых приложений - бесплатно ознакомительный отрывок. Жанр: comp-osnet, издательство Питер, год 2007. Здесь Вы можете читать ознакомительный отрывок из книги онлайн без регистрации и SMS на сайте лучшей интернет библиотеки ЛибКинг или прочесть краткое содержание (суть), предисловие и аннотацию. Так же сможете купить и скачать торрент в электронном формате fb2, найти и слушать аудиокнигу на русском языке или узнать сколько частей в серии и всего страниц в публикации. Читателям доступно смотреть обложку, картинки, описание и отзывы (комментарии) о произведении.
  • Название:
    UNIX: разработка сетевых приложений
  • Автор:
  • Жанр:
  • Издательство:
    Питер
  • Год:
    2007
  • Город:
    Санкт-Петербург
  • ISBN:
    5-94723-991-4
  • Рейтинг:
    4.33/5. Голосов: 91
  • Избранное:
    Добавить в избранное
  • Отзывы:
  • Ваша оценка:
    • 80
    • 1
    • 2
    • 3
    • 4
    • 5

Уильям Стивенс - UNIX: разработка сетевых приложений краткое содержание

UNIX: разработка сетевых приложений - описание и краткое содержание, автор Уильям Стивенс, читайте бесплатно онлайн на сайте электронной библиотеки LibKing.Ru

Новое издание книги, посвященной созданию веб-серверов, клиент-серверных приложений или любого другого сетевого программного обеспечения в операционной системе UNIX, — классическое руководство по сетевым программным интерфейсам, в частности сокетам. Оно основано на трудах Уильяма Стивенса и полностью переработано и обновлено двумя ведущими экспертами по сетевому программированию. В книгу включено описание ключевых современных стандартов, реализаций и методов, она содержит большое количество иллюстрирующих примеров и может использоваться как учебник по программированию в сетях, так и в качестве справочника для опытных программистов.

UNIX: разработка сетевых приложений - читать онлайн бесплатно ознакомительный отрывок

UNIX: разработка сетевых приложений - читать книгу онлайн бесплатно (ознакомительный отрывок), автор Уильям Стивенс
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

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 sigset_t sigset_alrm;

10 socklen_t len;

11 struct sockaddr *preply_addr;

12 preply_addr = Malloc(servlen);

13 Setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on));

14 Sigemptyset(&sigset_alrm);

15 Sigaddset(&sigset_alrm, SIGALRM);

16 Signal(SIGALRM, recvfrom_alarm);

17 while (Fgets(sendline, MAXLINE, fp) != NULL) {

18 Sendto(sockfd, sendline, strlen(sendline), 0, pservaddr, servlen);

19 alarm(5);

20 for (;;) {

21 len = servlen;

22 Sigprocmask(SIG_UNBLOCK, &sigset_alrm, NULL);

23 n = recvfrom(sockfd, recvline, MAXLINE, 0, preply_addr, &len);

24 Sigprocmask(SIG_BLOCK, &sigset_alrm, NULL);

25 if (n

26 if (errno == EINTR)

27 break; /* окончание ожидания ответа */

28 else

29 err_sys("recvfrom error");

30 } else {

31 recvline[n] = 0; /* завершающий нуль */

32 printf("from %s: %s",

33 Sock_ntop_host(preply_addr, len), recvline);

34 }

35 }

36 }

37 free(preply_addr);

38 }

39 static void

40 recvfrom_alarm(int signo)

41 {

42 return; /* выход из recvfrom() */

43 }

Объявление набора сигналов и инициализация

14-15 Мы объявляем набор сигналов, инициализируем его как пустой набор ( sigemptyset) и включаем бит, соответствующий сигналу SIGALRM( sigaddset).

Разблокирование и блокирование сигнала

21-24 Перед вызовом функции recvfromмы разблокируем сигнал (с тем, чтобы он мог быть доставлен, пока наша программа блокирована), а затем блокируем его, как только завершается функция recvfrom. Если сигнал генерируется (истекает время таймера), когда сигнал блокирован, то ядро запоминает этот факт, но доставить сигнал (то есть вызвать наш обработчик) не может, пока сигнал не будет разблокирован. В этом состоит принципиальная разница между генерацией сигнала и его доставкой . В главе 10 [110] предоставлена более подробная информация обо всех аспектах обработки сигналов POSIX.

Если мы откомпилируем и запустим эту программу, нам будет казаться, что она работает нормально, но все программы, порождающие ситуацию гонок, большую часть времени работают без каких-либо проблем! Проблема остается: разблокирование сигнала, вызов функции recvfromи блокирование сигнала — все эти действия являются независимыми системными вызовами. Будем считать, что функция recvfromвозвращает последний ответ на нашу дейтаграмму, а сигнал доставляется между вызовом функции recvfromи блокированием сигнала. Следующий вызов функции recvfromзаблокируется навсегда. Мы ограничили размер окна, но проблема осталась.

Вариантом решения может быть установка глобального флага при доставке сигнала его обработчиком:

recvfrom_alarm(int signo) {

had_alarm = 1;

return;

}

Флаг сбрасывается в 0 каждый раз, когда вызывается функция alarm. Наша функция dg_cliпроверяет этот флаг перед вызовом функции recvfromи не вызывает ее, если флаг ненулевой.

for (;;) {

len = servlen;

Sigprocmask(SIG_UNBLOCK, &sigset_alrm, NULL);

if (had_alarm == 1)

break;

n = recvfrom(sockfd, recvline, MAXLINE, 0, preply_addr, &len);

Если сигнал был сгенерирован во время его блокирования (после предыдущего возвращения из функции recvfrom), то после разблокирования в этой части кода он будет доставлен перед завершением функции sigprocmask, устанавливающей наш флаг. Однако между проверкой флага и вызовом функции recvfromсуществует промежуток времени, в течение которого сигнал может быть сгенерирован и доставлен, и если это произойдет, вызов функции recvfromзаблокируется навсегда (разумеется, мы считаем при этом, что не приходит никаких дополнительных ответов).

Блокирование и разблокирование сигнала с помощью функции pselect

Одним из корректных решений будет использование функции pselect(см. раздел 6.9), как показано в листинге 20.3.

Листинг 20.3. Блокирование и разблокирование сигналов с помощью функции pselect

//bcast/dgclibcast4.с

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 fd_set rset;

10 sigset_t sigset_alrm, sigset_empty;

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 FD_ZERO(&rset);

16 Sigemptyset(&sigset_empty);

17 Sigemptyset(&sigset_alrm);

18 Sigaddset(&sigset_alrm, SIGALRM);

19 Signal(SIGALRM, recvfrom_alarm);

20 while (Fgets(sendline, MAXLINE, fp) != NULL) {

21 Sendto(sockfd, sendline, strlen(sendline), 0, pservaddr, servlen);

22 Sigprocmask(SIG_BLOCK, &sigset_alrm, NULL);

23 alarm(5);

24 for (;;) {

25 FD_SET(sockfd, &rset);

26 n = pselect(sockfd + 1, &rset, NULL, NULL, NULL, &sigset_empty);

27 if (n

28 if (errno == EINTR)

29 break;

30 else

31 err_sys("pselect error");

32 } else if (n != 1)

33 err_sys("pselect error; returned %d", n);

34 len = servlen;

35 n = Recvfrom(sockfd, recvline, MAXLINE, 0, preply_addr, &len);

36 recvline[n] = 0; /* завершающий нуль */

37 printf("from %s: %s",

38 Sock_ntop_host(preply_addr, len), recvline);

39 }

40 }

41 free(preply_addr);

42 }

43 static void

44 recvfrom_alarm(int signo)

45 {

46 return; /* просто прерываем recvfrom() */

47 }

22-23 Мы блокируем сигнал SIGALRMи вызываем функцию pselect. Последний аргумент этой функции — указатель на нашу переменную sigset_empty, являющуюся набором сигналов, в котором нет блокированных сигналов (все сигналы разблокированы). Функция pselectсохранит текущую маску сигналов (которая блокирует SIGALRM), проверит заданные дескрипторы, заблокируется при необходимости с маской сигналов, установленной в пустой набор, но перед завершением функции маска сигналов процесса будет переустановлена в исходное значение, которое она имела при вызове функции pselect. Ключ к пониманию функции pselectв том, что установка маски сигналов, проверка дескрипторов и переустановка маски сигнала — это атомарные операции по отношению к вызывающему процессу.

34-38 Если наш сокет готов для чтения, мы вызываем функцию recvfrom, зная, что она не заблокируется.

Как мы упоминали в разделе 6.9, функция pselect— относительно новая среди других, описываемых спецификацией POSIX. Из всех систем, показанных на рис. 1.7, эту функцию поддерживают только FreeBSD и Linux. Тем не менее в листинге 20.4 представлена простая, хотя и некорректная ее реализация. Мы приводим ее здесь, несмотря на некорректность, чтобы продемонстрировать три стадии решения: установку маски сигнала в значение, заданное вызывающей функцией, с сохранением текущей маски, проверку дескрипторов и переустановку маски сигнала.

Читать дальше
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать


Уильям Стивенс читать все книги автора по порядку

Уильям Стивенс - все книги автора в одном месте читать по порядку полные версии на сайте онлайн библиотеки LibKing.




UNIX: разработка сетевых приложений отзывы


Отзывы читателей о книге UNIX: разработка сетевых приложений, автор: Уильям Стивенс. Читайте комментарии и мнения людей о произведении.


Понравилась книга? Поделитесь впечатлениями - оставьте Ваш отзыв или расскажите друзьям

Напишите свой комментарий
x