Вход/Регистрация
UNIX: разработка сетевых приложений
вернуться

Стивенс Уильям Ричард

Шрифт:

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

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 < 0) {

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);

  • Читать дальше
  • 1
  • ...
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: