Π§ΠΈΡ‚Π°ΠΉΡ‚Π΅ ΠΊΠ½ΠΈΠ³ΠΈ ΠΎΠ½Π»Π°ΠΉΠ½ Π½Π° Bookidrom.ru! БСсплатныС ΠΊΠ½ΠΈΠ³ΠΈ Π² ΠΎΠ΄Π½ΠΎΠΌ ΠΊΠ»ΠΈΠΊΠ΅

Π§ΠΈΡ‚Π°Ρ‚ΡŒ ΠΎΠ½Π»Π°ΠΉΠ½ Β«UNIX: Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° сСтСвых ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΉΒ». Π‘Ρ‚Ρ€Π°Π½ΠΈΡ†Π° 109

Автор Уильям БтивСнс

3. Π§Ρ‚ΠΎ ΠΏΡ€ΠΎΠΈΠ·ΠΎΠΉΠ΄Π΅Ρ‚, Ссли ΠΌΡ‹ создадим сокСт UDP, свяТСм ΠΏΠΎΡ€Ρ‚ 7 с сокСтом (стандартный эхо-сСрвСр Π² Ρ‚Π°Π±Π». 2.1) ΠΈ ΠΎΡ‚ΠΏΡ€Π°Π²ΠΈΠΌ Π΄Π΅ΠΉΡ‚Π°Π³Ρ€Π°ΠΌΠΌΡƒ UDP-сСрвСру chargen?

4. Π’ руководствС Solaris 2.x для Π΄Π΅ΠΌΠΎΠ½Π° inetd описываСтся Ρ„Π»Π°Π³ -t, Π·Π°ΡΡ‚Π°Π²Π»ΡΡŽΡ‰ΠΈΠΉ Π΄Π΅ΠΌΠΎΠ½ inetd Π²Ρ‹Π·Ρ‹Π²Π°Ρ‚ΡŒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ syslog (с Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚Π°ΠΌΠΈ facility=LOG_DAEMON ΠΈ level=LOG_NOTICE) для протоколирования клиСнтского IP-адрСса ΠΈ ΠΏΠΎΡ€Ρ‚Π° любой слуТбы TCP, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Π΅Ρ‚ Π΄Π΅ΠΌΠΎΠ½ inetd. Как Π΄Π΅ΠΌΠΎΠ½ inetd ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅Ρ‚ эту ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ?

Π’ этом ΠΆΠ΅ руководствС сказано, Ρ‡Ρ‚ΠΎ Π΄Π΅ΠΌΠΎΠ½ inetd Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ это для сокСта UDP. ΠŸΠΎΡ‡Π΅ΠΌΡƒ?

Π•ΡΡ‚ΡŒ Π»ΠΈ способ ΠΎΠ±ΠΎΠΉΡ‚ΠΈ эти ограничСния для слуТб UDP?

Π“Π»Π°Π²Π° 14

Π”ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π²Π²ΠΎΠ΄Π°-Π²Ρ‹Π²ΠΎΠ΄Π°

14.1. Π’Π²Π΅Π΄Π΅Π½ΠΈΠ΅

Π­Ρ‚Π° Π³Π»Π°Π²Π° ΠΎΡ…Π²Π°Ρ‚Ρ‹Π²Π°Π΅Ρ‚ Ρ€Π°Π·Π½ΠΎΠΎΠ±Ρ€Π°Π·Π½Ρ‹Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ ΠΈ Ρ‚Π΅Ρ…Π½ΠΎΠ»ΠΎΠ³ΠΈΠΈ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΌΡ‹ ΠΏΠΎΠΌΠ΅Ρ‰Π°Π΅ΠΌ Π² ΠΎΠ±Ρ‰ΡƒΡŽ ΠΊΠ°Ρ‚Π΅Π³ΠΎΡ€ΠΈΡŽ Β«Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½Π½ΠΎΠ³ΠΎ Π²Π²ΠΎΠ΄Π°-Π²Ρ‹Π²ΠΎΠ΄Π°Β». Π‘Π½Π°Ρ‡Π°Π»Π° ΠΌΡ‹ описываСм установку Ρ‚Π°ΠΉΠΌ-Π°ΡƒΡ‚Π° для ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ Π²Π²ΠΎΠ΄Π°-Π²Ρ‹Π²ΠΎΠ΄Π°, ΠΊΠΎΡ‚ΠΎΡ€ΡƒΡŽ ΠΌΠΎΠΆΠ½ΠΎ Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ трСмя Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹ΠΌΠΈ способами. Π—Π°Ρ‚Π΅ΠΌ ΠΌΡ‹ рассматриваСм Ρ‚Ρ€ΠΈ Π²Π°Ρ€ΠΈΠ°Π½Ρ‚Π° Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ read ΠΈ write: recv ΠΈ send, Π΄ΠΎΠΏΡƒΡΠΊΠ°ΡŽΡ‰ΠΈΠ΅ Ρ‡Π΅Ρ‚Π²Π΅Ρ€Ρ‚Ρ‹ΠΉ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚, содСрТащий Ρ„Π»Π°Π³ΠΈ, ΠΏΠ΅Ρ€Π΅Π΄Π°Π²Π°Π΅ΠΌΡ‹Π΅ ΠΎΡ‚ процСсса ΠΊ ядру; readv ΠΈ writev, ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡŽΡ‰ΠΈΠ΅ Π½Π°ΠΌ Π·Π°Π΄Π°Π²Π°Ρ‚ΡŒ массив Π±ΡƒΡ„Π΅Ρ€ΠΎΠ² для Π²Π²ΠΎΠ΄Π° ΠΈΠ»ΠΈ Π²Ρ‹Π²ΠΎΠ΄Π°; recvmsg ΠΈ sendmsg, ΠΎΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΡŽΡ‰ΠΈΠ΅ всС свойства Π΄Ρ€ΡƒΠ³ΠΈΡ… Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ Π²Π²ΠΎΠ΄Π°-Π²Ρ‹Π²ΠΎΠ΄Π° ΠΈ ΠΎΠ±Π»Π°Π΄Π°ΡŽΡ‰ΠΈΠ΅ Π½ΠΎΠ²ΠΎΠΉ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒΡŽ получСния ΠΈ ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΠΈ Π²ΡΠΏΠΎΠΌΠΎΠ³Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹Ρ… Π΄Π°Π½Π½Ρ‹Ρ….

ΠœΡ‹ Ρ‚Π°ΠΊΠΆΠ΅ рассказываСм ΠΎ Ρ‚ΠΎΠΌ, ΠΊΠ°ΠΊ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΡ‚ΡŒ, сколько Π΄Π°Π½Π½Ρ‹Ρ… находится Π² ΠΏΡ€ΠΈΠ΅ΠΌΠ½ΠΎΠΌ Π±ΡƒΡ„Π΅Ρ€Π΅ сокСта ΠΈ ΠΊΠ°ΠΊ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ с сокСтами ΡΡ‚Π°Π½Π΄Π°Ρ€Ρ‚Π½ΡƒΡŽ Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΡƒ Π²Π²ΠΎΠ΄Π°-Π²Ρ‹Π²ΠΎΠ΄Π° Π‘, ΠΈ обсуТдаСм Π±ΠΎΠ»Π΅Π΅ ΡΠΎΠ²Π΅Ρ€ΡˆΠ΅Π½Π½Ρ‹Π΅ способы оТидания событий.

14.2. Π’Π°ΠΉΠΌ-Π°ΡƒΡ‚Ρ‹ сокСта

БущСствуСт Ρ‚Ρ€ΠΈ способа установки Ρ‚Π°ΠΉΠΌ-Π°ΡƒΡ‚Π° для ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ Π²Π²ΠΎΠ΄Π°-Π²Ρ‹Π²ΠΎΠ΄Π° Ρ‡Π΅Ρ€Π΅Π· сокСт.

1. Π’Ρ‹Π·ΠΎΠ² Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ alarm, которая Π³Π΅Π½Π΅Ρ€ΠΈΡ€ΡƒΠ΅Ρ‚ сигнал SIGALRM, ΠΊΠΎΠ³Π΄Π° истСкаСт Π·Π°Π΄Π°Π½Π½ΠΎΠ΅ врСмя. Π­Ρ‚ΠΎ ΠΏΠΎΠ΄Ρ€Π°Π·ΡƒΠΌΠ΅Π²Π°Π΅Ρ‚ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΡƒ сигналов, которая ΠΌΠΎΠΆΠ΅Ρ‚ Π²Π°Ρ€ΡŒΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒΡΡ ΠΎΡ‚ ΠΎΠ΄Π½ΠΎΠΉ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ ΠΊ Π΄Ρ€ΡƒΠ³ΠΎΠΉ. К Ρ‚ΠΎΠΌΡƒ ΠΆΠ΅ Ρ‚Π°ΠΊΠΎΠΉ ΠΏΠΎΠ΄Ρ…ΠΎΠ΄ ΠΌΠΎΠΆΠ΅Ρ‚ ΡΡ‚Π°Ρ‚ΡŒ ΠΏΠΎΠΌΠ΅Ρ…ΠΎΠΉ Π΄Ρ€ΡƒΠ³ΠΈΠΌ ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΌ Π²Ρ‹Π·ΠΎΠ²Π°ΠΌ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ alarm Π² Π΄Π°Π½Π½ΠΎΠΌ процСссС.

2. Π‘Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ ΠΏΡ€ΠΈ ΠΎΠΆΠΈΠ΄Π°Π½ΠΈΠΈ Π²Π²ΠΎΠ΄Π°-Π²Ρ‹Π²ΠΎΠ΄Π° Π² Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ select, ΠΈΠΌΠ΅ΡŽΡ‰Π΅ΠΉ встроСнноС ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΠ΅ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ, вмСсто блокирования Π² Π²Ρ‹Π·ΠΎΠ²Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ read ΠΈΠ»ΠΈ write.

3. Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ Π±ΠΎΠ»Π΅Π΅ Π½ΠΎΠ²Ρ‹Ρ… ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠ² сокСта β€” SO_RCVTIMEO ΠΈ SO_SNDTIMEO. ΠŸΡ€ΠΎΠ±Π»Π΅ΠΌΠ° ΠΏΡ€ΠΈ использовании этого ΠΏΠΎΠ΄Ρ…ΠΎΠ΄Π° Π·Π°ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ΡΡ Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ Π½Π΅ всС Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°ΡŽΡ‚ Π½ΠΎΠ²Ρ‹Π΅ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Ρ‹ сокСтов.

ВсС Ρ‚Ρ€ΠΈ Ρ‚Π΅Ρ…Π½ΠΎΠ»ΠΎΠ³ΠΈΠΈ Ρ€Π°Π±ΠΎΡ‚Π°ΡŽΡ‚ с функциями Π²Π²ΠΎΠ΄Π° ΠΈ Π²Ρ‹Π²ΠΎΠ΄Π° (Ρ‚Π°ΠΊΠΈΠΌΠΈ ΠΊΠ°ΠΊ read, write ΠΈ ΠΈΡ… вариациями, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€ recvfrom ΠΈ sendto), Π½ΠΎ Π½Π°ΠΌ Ρ‚Π°ΠΊΠΆΠ΅ Ρ…ΠΎΡ‚Π΅Π»ΠΎΡΡŒ Π±Ρ‹ ΠΈΠΌΠ΅Ρ‚ΡŒ Ρ‚Π΅Ρ…Π½ΠΎΠ»ΠΎΠ³ΠΈΡŽ, Ρ€Π°Π±ΠΎΡ‚Π°ΡŽΡ‰ΡƒΡŽ с Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠ΅ΠΉ connect, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ процСсс соСдинСния TCP ΠΌΠΎΠΆΠ΅Ρ‚ Π·Π°Π½ΡΡ‚ΡŒ Π΄Π»ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΠ΅ врСмя (ΠΎΠ±Ρ‹Ρ‡Π½ΠΎ 75 с). Π€ΡƒΠ½ΠΊΡ†ΠΈΡŽ select ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ для установки Ρ‚Π°ΠΉΠΌ-Π°ΡƒΡ‚Π° Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ connect, Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΊΠΎΠ³Π΄Π° сокСт находится Π² Π½Π΅Π±Π»ΠΎΠΊΠΈΡ€ΡƒΠ΅ΠΌΠΎΠΌ Ρ€Π΅ΠΆΠΈΠΌΠ΅ (ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΌΡ‹ рассматриваСм Π² Ρ€Π°Π·Π΄Π΅Π»Π΅ 16.3), Π° ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Ρ‹ сокСтов, ΡƒΡΡ‚Π°Π½Π°Π²Π»ΠΈΠ²Π°ΡŽΡ‰ΠΈΠ΅ Ρ‚Π°ΠΉΠΌ-Π°ΡƒΡ‚, Π½Π΅ Ρ€Π°Π±ΠΎΡ‚Π°ΡŽΡ‚ с Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠ΅ΠΉ connect. ΠœΡ‹ Ρ‚Π°ΠΊΠΆΠ΅ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ ΠΎΡ‚ΠΌΠ΅Ρ‚ΠΈΡ‚ΡŒ, Ρ‡Ρ‚ΠΎ ΠΏΠ΅Ρ€Π²Ρ‹Π΅ Π΄Π²Π΅ Ρ‚Π΅Ρ…Π½ΠΎΠ»ΠΎΠ³ΠΈΠΈ Ρ€Π°Π±ΠΎΡ‚Π°ΡŽΡ‚ с Π»ΡŽΠ±Ρ‹ΠΌ дСскриптором, Π² Ρ‚ΠΎ врСмя ΠΊΠ°ΠΊ Ρ‚Ρ€Π΅Ρ‚ΡŒΡ тСхнология Ρ‚ΠΎΠ»ΡŒΠΊΠΎ с дСскрипторами сокСтов.

Π’Π΅ΠΏΠ΅Ρ€ΡŒ ΠΌΡ‹ прСдставим ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρ‹ примСнСния всСх Ρ‚Ρ€Π΅Ρ… Ρ‚Π΅Ρ…Π½ΠΎΠ»ΠΎΠ³ΠΈΠΉ.

Π’Π°ΠΉΠΌ-Π°ΡƒΡ‚ для Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ connect (сигнал SIGALRM)

Π’ листингС 14.1[1] ΠΏΠΎΠΊΠ°Π·Π°Π½Π° наша функция connect_timeo, Π²Ρ‹Π·Ρ‹Π²Π°ΡŽΡ‰Π°Ρ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ connect с ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΠ΅ΠΌ ΠΏΠΎ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ, Π·Π°Π΄Π°Π½Π½Ρ‹ΠΌ Π²Ρ‹Π·Ρ‹Π²Π°ΡŽΡ‰ΠΈΠΌ процСссом. ΠŸΠ΅Ρ€Π²Ρ‹Π΅ Ρ‚Ρ€ΠΈ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚Π° β€” это Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚Ρ‹, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… Ρ‚Ρ€Π΅Π±ΡƒΠ΅Ρ‚ функция connect, Π° Ρ‡Π΅Ρ‚Π²Π΅Ρ€Ρ‚Ρ‹ΠΉ β€” это Π΄Π»ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ оТидания Π² сСкундах.

Листинг 14.1. Ѐункция connect с Ρ‚Π°ΠΉΠΌ-Π°ΡƒΡ‚ΠΎΠΌ

//lib/connect_timeo.c

 1 #include "unp.h"


 2 static void connect_alarm(int);


 3 int

 4 connect_timeo(int sockfd, const SA *saptr, socklen_t salen, int nsec)

 5 {

 6  Sigfunc *sigfunc;

 7  int n;


 8  sigfunc = Signal(SIGALRM, connect_alarm);

 9  if (alarm(nsec) != 0)

10   err_msg("connect_timeo: alarm was already set");


11  if ((n = connect(sockfd, saptr, salen)) < 0) {

12   close(sockfd);

13   if (errno == EINTR)

14    errno = ETIMEDOUT;

15  }

16  alarm(0); /* ΠΎΡ‚ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ alarm */

17  Signal(SIGALRM, sigfunc); /* восстанавливаСм ΠΏΡ€Π΅ΠΆΠ½ΠΈΠΉ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ

                                 сигнала */

18  return (n);

19 }


20 static void

21 connect_alarm(int signo)

22 {

23  return; /* просто ΠΏΡ€Π΅Ρ€Ρ‹Π²Π°Π΅ΠΌ connect() */

24 }

Установка ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠ° сигналов

8 Π”ля SIGALRM устанавливаСтся ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ сигнала. Π’Π΅ΠΊΡƒΡ‰ΠΈΠΉ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ сигнала (Ссли Ρ‚Π°ΠΊΠΎΠ²ΠΎΠΉ имССтся) сохраняСтся, ΠΈ Ρ‚Π°ΠΊΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ Π²ΠΎΡΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ Π΅Π³ΠΎ Π² ΠΊΠΎΠ½Ρ†Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ.

Установка Ρ‚Π°ΠΉΠΌΠ΅Ρ€Π°

9-10 Π’Π°ΠΉΠΌΠ΅Ρ€ для процСсса устанавливаСтся Π½Π° врСмя (число сСкунд), Π·Π°Π΄Π°Π½Π½ΠΎΠ΅ Π²Ρ‹Π·Ρ‹Π²Π°ΡŽΡ‰ΠΈΠΌ процСссом. Π’ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅ΠΌΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ alarm β€” это число сСкунд, ΠΎΡΡ‚Π°ΡŽΡ‰ΠΈΡ…ΡΡ Π² Ρ‚Π°ΠΉΠΌΠ΅Ρ€Π΅ для процСсса (Ссли ΠΎΠ½ ΡƒΠΆΠ΅ установлСн для процСсса) Π² настоящий ΠΌΠΎΠΌΠ΅Π½Ρ‚ ΠΈΠ»ΠΈ 0 (Ссли Ρ‚Π°ΠΉΠΌΠ΅Ρ€ Π½Π΅ Π±Ρ‹Π» установлСн ΠΏΡ€Π΅ΠΆΠ΄Π΅). Π’ ΠΏΠ΅Ρ€Π²ΠΎΠΌ случаС ΠΌΡ‹ Π²Ρ‹Π²ΠΎΠ΄ΠΈΠΌ сообщСниС с ΠΏΡ€Π΅Π΄ΡƒΠΏΡ€Π΅ΠΆΠ΄Π΅Π½ΠΈΠ΅ΠΌ, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΌΡ‹ стираСм ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰ΡƒΡŽ установку Ρ‚Π°ΠΉΠΌΠ΅Ρ€Π° (см. ΡƒΠΏΡ€Π°ΠΆΠ½Π΅Π½ΠΈΠ΅ 14.2).

Π’Ρ‹Π·ΠΎΠ² Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ connect

11-15 Π’ызываСтся функция connect, ΠΈ Ссли функция прСрываСтся (EINTR), ΠΌΡ‹ присваиваСм ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ errno Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ETIMEDOUT. Π‘ΠΎΠΊΠ΅Ρ‚ закрываСтся, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π½Π΅ Π΄ΠΎΠΏΡƒΡΡ‚ΠΈΡ‚ΡŒ продолТСния трСхэтапного рукопоТатия.

Π’Ρ‹ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ Ρ‚Π°ΠΉΠΌΠ΅Ρ€Π° ΠΈ восстановлСниС ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰Π΅Π³ΠΎ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠ° сигнала

16-18 Π’Π°ΠΉΠΌΠ΅Ρ€ ΠΏΡ€ΠΈ ΠΎΠ±Π½ΡƒΠ»Π΅Π½ΠΈΠΈ Π²Ρ‹ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ΡΡ, ΠΈ восстанавливаСтся ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰ΠΈΠΉ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ сигналов (Ссли Ρ‚Π°ΠΊΠΎΠ²ΠΎΠΉ имССтся).

ΠžΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° сигнала SIGALRM

20-24 ΠžΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ сигнала просто Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅. ΠŸΡ€Π΅Π΄ΠΏΠΎΠ»Π°Π³Π°Π΅Ρ‚ΡΡ, Ρ‡Ρ‚ΠΎ это ΠΏΡ€Π΅Ρ€Π²Π΅Ρ‚ ΠΎΠΆΠΈΠ΄Π°Π½ΠΈΠ΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ connect, заставив Π΅Π΅ Π²ΠΎΠ·Π²Ρ€Π°Ρ‚ΠΈΡ‚ΡŒ ΠΎΡˆΠΈΠ±ΠΊΡƒ EINTR. ВспомнитС Π½Π°ΡˆΡƒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ signal (см. листинг 5.5), которая Π½Π΅ устанавливаСт Ρ„Π»Π°Π³Π° SA_RESTART, ΠΊΠΎΠ³Π΄Π° ΠΏΠ΅Ρ€Π΅Ρ…Π²Π°Ρ‚Ρ‹Π²Π°Π΅ΠΌΡ‹ΠΉ сигнал β€” это сигнал SIGALRM.

Одним ΠΈΠ· Π²Π°ΠΆΠ½Ρ‹Ρ… ΠΌΠΎΠΌΠ΅Π½Ρ‚ΠΎΠ² Π² этом ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅ являСтся Ρ‚ΠΎ, Ρ‡Ρ‚ΠΎ ΠΌΡ‹ всСгда ΠΌΠΎΠΆΠ΅ΠΌ ΡΠΎΠΊΡ€Π°Ρ‚ΠΈΡ‚ΡŒ ΠΏΠ΅Ρ€ΠΈΠΎΠ΄ оТидания для Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ connect, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ эту Ρ‚Π΅Ρ…Π½ΠΎΠ»ΠΎΠ³ΠΈΡŽ, Π½ΠΎ ΠΌΡ‹ Π½Π΅ ΠΌΠΎΠΆΠ΅ΠΌ ΡƒΠ²Π΅Π»ΠΈΡ‡ΠΈΡ‚ΡŒ ΠΏΠ΅Ρ€ΠΈΠΎΠ΄, Π·Π°Π΄Π°Π½Π½Ρ‹ΠΉ для ядра. Π’ Π‘Π΅Ρ€ΠΊΠ»ΠΈ-ядрС Ρ‚Π°ΠΉΠΌ-Π°ΡƒΡ‚ для Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ connect ΠΎΠ±Ρ‹Ρ‡Π½ΠΎ Ρ€Π°Π²Π΅Π½ 75 с. ΠœΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ Π·Π°Π΄Π°Ρ‚ΡŒ мСньшСС Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ для нашСй Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, допустим 10, Π½ΠΎ Ссли ΠΌΡ‹ Π·Π°Π΄Π°Π΅ΠΌ большСС Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅, скаТСм 80, Ρ‚Π°ΠΉΠΌ- Π°ΡƒΡ‚ самой Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ connect всС Ρ€Π°Π²Π½ΠΎ составит 75 с.

Π”Ρ€ΡƒΠ³ΠΎΠΉ Π²Π°ΠΆΠ½Ρ‹ΠΉ ΠΌΠΎΠΌΠ΅Π½Ρ‚ Π² Π΄Π°Π½Π½ΠΎΠΌ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅ β€” Ρ‚ΠΎ, Ρ‡Ρ‚ΠΎ ΠΌΡ‹ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ прСрывания систСмного Π²Ρ‹Π·ΠΎΠ²Π° (connect) для Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π²ΠΎΠ·Π²Ρ€Π°Ρ‚ΠΈΡ‚ΡŒ ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅, ΠΏΡ€Π΅ΠΆΠ΄Π΅ Ρ‡Π΅ΠΌ истСчСт врСмя оТидания ядра. Π’Π°ΠΊΠΎΠΉ ΠΏΠΎΠ΄Ρ…ΠΎΠ΄ допустим, ΠΊΠΎΠ³Π΄Π° ΠΌΡ‹ выполняСм систСмный Π²Ρ‹Π·ΠΎΠ² ΠΈ ΠΌΠΎΠΆΠ΅ΠΌ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π΅Π½ΠΈΠ΅ ошибки EINTR. Но Π² Ρ€Π°Π·Π΄Π΅Π»Π΅ 29.7 ΠΌΡ‹ встрСтимся с Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅Ρ‡Π½ΠΎΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠ΅ΠΉ, Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡŽΡ‰Π΅ΠΉ систСмный Π²Ρ‹Π·ΠΎΠ², которая сама выполняСт Π·Π°Π½ΠΎΠ²ΠΎ систСмный Π²Ρ‹Π·ΠΎΠ² ΠΏΡ€ΠΈ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π΅Π½ΠΈΠΈ ошибки EINTR. ΠœΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ ΠΏΡ€ΠΎΠ΄ΠΎΠ»ΠΆΠ°Ρ‚ΡŒ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ с сигналом SIGALRM ΠΈ Π² этом случаС, Π½ΠΎ Π² листингС 29.6 ΠΌΡ‹ ΡƒΠ²ΠΈΠ΄ΠΈΠΌ, Ρ‡Ρ‚ΠΎ Π½Π°ΠΌ придСтся Π²ΠΎΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒΡΡ функциями sigsetjmp ΠΈ siglongjmp, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ библиотСчная функция ΠΈΠ³Π½ΠΎΡ€ΠΈΡ€ΡƒΠ΅Ρ‚ ΠΎΡˆΠΈΠ±ΠΊΡƒ EINTR.

Π’Π°ΠΉΠΌ-Π°ΡƒΡ‚ для Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ recvfrom (сигнал SIGALRM)

Π’ листингС 14.2 ΠΏΠΎΠΊΠ°Π·Π°Π½Π° новая вСрсия Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ dg_cli, ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅Π½Π½ΠΎΠΉ Π² листингС 8.4, Π² ΠΊΠΎΡ‚ΠΎΡ€ΡƒΡŽ Π΄ΠΎΠ±Π°Π²Π»Π΅Π½ Π²Ρ‹Π·ΠΎΠ² Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ alarm для прСрывания Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ recvfrom ΠΏΡ€ΠΈ отсутствии ΠΎΡ‚Π²Π΅Ρ‚Π° Π² Ρ‚Π΅Ρ‡Π΅Π½ΠΈΠ΅ 5 Ρ.

Листинг 14.2. Ѐункция dg_cli, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ ΠΏΡ€ΠΈ установкС Ρ‚Π°ΠΉΠΌ-Π°ΡƒΡ‚Π° для Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ recvfrom ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ функция alarm

//advio/dgclitimeo3.c

 1 #include "unp.h"


 2 static void signalrm(int);


 3 void

 4 dg_cli(FILE *fp, int sockfd, const SA *pservaddr, socklen_t servlen)

 5 {

 6  int n;

 7  char sendline[MAXLINE], recvline[MAXLINE + 1];


 8  Signal(SIGALRM, signalrm);


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


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


11   alarm(5);

12   if ((n = recvfrom(sockfd, recvline, MAXLINE, 0, NULL, NULL)) < 0) {

13    if (errno == EINTR)

14     fprintf(stderr, "socket timeout\n");

15    else

16     err_sys("recvfrom error");

17   } else {

18    alarm(0);

19    recvline[n] = 0; /* Π·Π°Π²Π΅Ρ€ΡˆΠ°ΡŽΡ‰ΠΈΠΉ Π½ΡƒΠ»ΡŒ */

20    Fputs(recvline, stdout);

21   }

22  }

23 }


24 static void

25 sig_alrm(int signo)

26 {

27  return; /* просто ΠΏΡ€Π΅Ρ€Ρ‹Π²Π°Π΅ΠΌ recvfrom() */

28 }

ΠžΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° Ρ‚Π°ΠΉΠΌ-Π°ΡƒΡ‚Π° ΠΈΠ· Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ recvfrom

8-22 ΠœΡ‹ устанавливаСм ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ для сигнала SIGALRM ΠΈ Π·Π°Ρ‚Π΅ΠΌ Π²Ρ‹Π·Ρ‹Π²Π°Π΅ΠΌ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ alarm для 5-сСкундного Ρ‚Π°ΠΉΠΌ-Π°ΡƒΡ‚Π° ΠΏΡ€ΠΈ ΠΊΠ°ΠΆΠ΄ΠΎΠΌ Π²Ρ‹Π·ΠΎΠ²Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ recvfrom. Если функция recvfrom прСрываСтся нашим ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΎΠΌ сигнала, ΠΌΡ‹ Π²Ρ‹Π²ΠΎΠ΄ΠΈΠΌ сообщСниС ΠΎΠ± ошибкС ΠΈ ΠΏΡ€ΠΎΠ΄ΠΎΠ»ΠΆΠ°Π΅ΠΌ Ρ€Π°Π±ΠΎΡ‚Ρƒ. Если ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½Π° строка ΠΎΡ‚ сСрвСра, ΠΌΡ‹ ΠΎΡ‚ΠΊΠ»ΡŽΡ‡Π°Π΅ΠΌ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ alarm ΠΈ Π²Ρ‹Π²ΠΎΠ΄ΠΈΠΌ ΠΎΡ‚Π²Π΅Ρ‚.