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

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

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

Π‘Ρ€Π°Π²Π½Π΅Π½ΠΈΠ΅ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ выполнСния Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹Ρ… вСрсий Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ str_cli

Π˜Ρ‚Π°ΠΊ, ΠΌΡ‹ продСмонстрировали Ρ‡Π΅Ρ‚Ρ‹Ρ€Π΅ Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹Ρ… вСрсии Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ str_cli. Для ΠΊΠ°ΠΆΠ΄ΠΎΠΉ вСрсии ΠΌΡ‹ ΠΏΠΎΠΊΠ°ΠΆΠ΅ΠΌ врСмя, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ ΠΏΠΎΡ‚Ρ€Π΅Π±ΠΎΠ²Π°Π»ΠΎΡΡŒ для Π΅Π΅ выполнСния, Π² Ρ‚ΠΎΠΌ числС ΠΈ для вСрсии, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‰Π΅ΠΉ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½Ρ‹Π΅ ΠΏΠΎΡ‚ΠΎΠΊΠΈ (см. листинг 26.1). Π’ ΠΊΠ°ΠΆΠ΄ΠΎΠΌ случаС Π±Ρ‹Π»ΠΎ скопировано 2000 строк ΠΎΡ‚ ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π° Solaris ΠΊ сСрвСру с ΠΏΠ΅Ρ€ΠΈΠΎΠ΄ΠΎΠΌ RTT, Ρ€Π°Π²Π½Ρ‹ΠΌ 175 мс:

β–  354,0 с, Ρ€Π΅ΠΆΠΈΠΌ остановки ΠΈ оТидания (см. листинг 5.4);

β–  12,3 с, функция select ΠΈ Π±Π»ΠΎΠΊΠΈΡ€ΡƒΠ΅ΠΌΡ‹ΠΉ Π²Π²ΠΎΠ΄-Π²Ρ‹Π²ΠΎΠ΄ (см. листинг 6.2);

β–  6,9 с, Π½Π΅Π±Π»ΠΎΠΊΠΈΡ€ΡƒΠ΅ΠΌΡ‹ΠΉ Π²Π²ΠΎΠ΄-Π²Ρ‹Π²ΠΎΠ΄ (см. листинг 16.1);

β–  8,7 с, функция fork (см. листинг 16.6);

β–  8,5 с, вСрсия с ΠΏΠΎΡ‚ΠΎΠΊΠ°ΠΌΠΈ (см. листинг 26.1).

Наша вСрсия с Π½Π΅Π±Π»ΠΎΠΊΠΈΡ€ΡƒΠ΅ΠΌΡ‹ΠΌ Π²Π²ΠΎΠ΄ΠΎΠΌ-Π²Ρ‹Π²ΠΎΠ΄ΠΎΠΌ ΠΏΠΎΡ‡Ρ‚ΠΈ Π²Π΄Π²ΠΎΠ΅ быстрСС вСрсии, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‰Π΅ΠΉ Π±Π»ΠΎΠΊΠΈΡ€ΡƒΠ΅ΠΌΡ‹ΠΉ Π²Π²ΠΎΠ΄-Π²Ρ‹Π²ΠΎΠ΄ с Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠ΅ΠΉ select. Наша простая вСрсия с ΠΏΡ€ΠΈΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ΠΌ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ fork ΠΌΠ΅Π΄Π»Π΅Π½Π½Π΅Π΅ вСрсии с Π½Π΅Π±Π»ΠΎΠΊΠΈΡ€ΡƒΠ΅ΠΌΡ‹ΠΌ Π²Π²ΠΎΠ΄ΠΎΠΌ- Π²Ρ‹Π²ΠΎΠ΄ΠΎΠΌ. Π’Π΅ΠΌ Π½Π΅ ΠΌΠ΅Π½Π΅Π΅, учитывая ΡΠ»ΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ ΠΊΠΎΠ΄Π° Π½Π΅Π±Π»ΠΎΠΊΠΈΡ€ΡƒΠ΅ΠΌΠΎΠ³ΠΎ Π²Π²ΠΎΠ΄Π°-Π²Ρ‹Π²ΠΎΠ΄Π° ΠΏΠΎ ΡΡ€Π°Π²Π½Π΅Π½ΠΈΡŽ с ΠΊΠΎΠ΄ΠΎΠΌ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ fork, ΠΌΡ‹ Ρ€Π΅ΠΊΠΎΠΌΠ΅Π½Π΄ΡƒΠ΅ΠΌ Π±ΠΎΠ»Π΅Π΅ простой ΠΏΠΎΠ΄Ρ…ΠΎΠ΄.

16.3. НСблокируСмая функция connect

Когда сокСт TCP устанавливаСтся ΠΊΠ°ΠΊ Π½Π΅Π±Π»ΠΎΠΊΠΈΡ€ΡƒΠ΅ΠΌΡ‹ΠΉ, Π° Π·Π°Ρ‚Π΅ΠΌ вызываСтся функция connect, ΠΎΠ½Π° Π½Π΅ΠΌΠ΅Π΄Π»Π΅Π½Π½ΠΎ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ ΠΎΡˆΠΈΠ±ΠΊΡƒ EINPROGRESS, ΠΎΠ΄Π½Π°ΠΊΠΎ трСхэтапноС Ρ€ΡƒΠΊΠΎΠΏΠΎΠΆΠ°Ρ‚ΠΈΠ΅ TCP продолТаСтся. Π”Π°Π»Π΅Π΅ ΠΌΡ‹ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ select провСряСм, ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎ ΠΈΠ»ΠΈ Π½Π΅Ρ‚ Π·Π°Π²Π΅Ρ€ΡˆΠΈΠ»ΠΎΡΡŒ установлСниС соСдинСния. НСблокируСмая функция connect Π½Π°Ρ…ΠΎΠ΄ΠΈΡ‚ ΠΏΡ€ΠΈΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ Π² Ρ‚Ρ€Π΅Ρ… случаях:

1. Π’рСхэтапноС Ρ€ΡƒΠΊΠΎΠΏΠΎΠΆΠ°Ρ‚ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ Π½Π°Π»ΠΎΠΆΠΈΡ‚ΡŒΡΡ Π½Π° ΠΊΠ°ΠΊΠΎΠΉ-Π»ΠΈΠ±ΠΎ Π΄Ρ€ΡƒΠ³ΠΎΠΉ процСсс. Для выполнСния Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ connect трСбуСтся ΠΎΠ΄ΠΈΠ½ ΠΏΠ΅Ρ€ΠΈΠΎΠ΄ обращСния RTT (см. Ρ€Π°Π·Π΄Π΅Π» 2.5), ΠΈ это ΠΌΠΎΠΆΠ΅Ρ‚ Π·Π°Π½ΡΡ‚ΡŒ ΠΎΡ‚ Π½Π΅ΡΠΊΠΎΠ»ΡŒΠΊΠΈΡ… миллисСкунд Π² локальной сСти Π΄ΠΎ сотСн миллисСкунд ΠΈΠ»ΠΈ Π½Π΅ΡΠΊΠΎΠ»ΡŒΠΊΠΈΡ… сСкунд Π² глобальной сСти. Π­Ρ‚ΠΎ врСмя ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ провСсти с пользой, выполняя ΠΊΠ°ΠΊΠΎΠΉ-Π»ΠΈΠ±ΠΎ Π΄Ρ€ΡƒΠ³ΠΎΠΉ процСсс.

2. ΠœΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ ΡƒΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ мноТСство соСдинСний ΠΎΠ΄Π½ΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎ, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ эту Ρ‚Π΅Ρ…Π½ΠΎΠ»ΠΎΠ³ΠΈΡŽ. Π­Ρ‚ΠΎΡ‚ способ ΡƒΠΆΠ΅ стал популярСн Π² ΠΏΡ€ΠΈΠΌΠ΅Π½Π΅Π½ΠΈΠΈ ΠΊ Π²Π΅Π±-Π±Ρ€Π°ΡƒΠ·Π΅Ρ€Π°ΠΌ, ΠΈ Ρ‚Π°ΠΊΠΎΠΉ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ ΠΌΡ‹ ΠΏΡ€ΠΈΠ²ΠΎΠ΄ΠΈΠΌ Π² Ρ€Π°Π·Π΄Π΅Π»Π΅ 16.5.

3. ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΌΡ‹ ΠΆΠ΄Π΅ΠΌ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ установлСния соСдинСния с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ select, ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ Π·Π°Π΄Π°Ρ‚ΡŒ ΠΏΡ€Π΅Π΄Π΅Π» Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ для Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ select, Ρ‡Ρ‚ΠΎ ΠΏΠΎΠ·Π²ΠΎΠ»ΠΈΡ‚ Π½Π°ΠΌ ΡΠΎΠΊΡ€Π°Ρ‚ΠΈΡ‚ΡŒ Ρ‚Π°ΠΉΠΌ-Π°ΡƒΡ‚ для Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ connect. Π’ΠΎ ΠΌΠ½ΠΎΠ³ΠΈΡ… рСализациях Ρ‚Π°ΠΉΠΌ-Π°ΡƒΡ‚ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ connect Π»Π΅ΠΆΠΈΡ‚ Π² ΠΏΡ€Π΅Π΄Π΅Π»Π°Ρ… ΠΎΡ‚ 75 с Π΄ΠΎ Π½Π΅ΡΠΊΠΎΠ»ΡŒΠΊΠΈΡ… ΠΌΠΈΠ½ΡƒΡ‚. Π‘Ρ‹Π²Π°ΡŽΡ‚ случаи, ΠΊΠΎΠ³Π΄Π° ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡŽ Π½ΡƒΠΆΠ΅Π½ Π±ΠΎΠ»Π΅Π΅ ΠΊΠΎΡ€ΠΎΡ‚ΠΊΠΈΠΉ Ρ‚Π°ΠΉΠΌ-Π°ΡƒΡ‚, ΠΈ ΠΎΠ΄Π½ΠΈΠΌ ΠΈΠ· Ρ€Π΅ΡˆΠ΅Π½ΠΈΠΉ ΠΌΠΎΠΆΠ΅Ρ‚ ΡΡ‚Π°Ρ‚ΡŒ использованиС Π½Π΅Π±Π»ΠΎΠΊΠΈΡ€ΡƒΠ΅ΠΌΠΎΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ connect. Π’ Ρ€Π°Π·Π΄Π΅Π»Π΅ 14.2 Ρ€Π°ΡΡΠΌΠ°Ρ‚Ρ€ΠΈΠ²Π°ΡŽΡ‚ΡΡ Π΄Ρ€ΡƒΠ³ΠΈΠ΅ способы помСщСния Ρ‚Π°ΠΉΠΌ-Π°ΡƒΡ‚Π° Π² ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ с сокСтами.

Как Π±Ρ‹ просто Π½ΠΈ выглядСла нСблокируСмая функция connect, Π΅ΡΡ‚ΡŒ ряд ΠΌΠΎΠΌΠ΅Π½Ρ‚ΠΎΠ², ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ слСдуСт ΡƒΡ‡ΠΈΡ‚Ρ‹Π²Π°Ρ‚ΡŒ.

β–  Π”Π°ΠΆΠ΅ Ссли сокСт являСтся Π½Π΅Π±Π»ΠΎΠΊΠΈΡ€ΡƒΠ΅ΠΌΡ‹ΠΌ, Ρ‚ΠΎ ΠΊΠΎΠ³Π΄Π° сСрвСр, с ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΌ ΠΌΡ‹ соСдиняСмся, находится Π½Π° Ρ‚ΠΎΠΌ ΠΆΠ΅ ΡƒΠ·Π»Π΅, ΠΎΠ±Ρ‹Ρ‡Π½ΠΎ установлСниС соСдинСния происходит Π½Π΅ΠΌΠ΅Π΄Π»Π΅Π½Π½ΠΎ ΠΏΡ€ΠΈ Π²Ρ‹Π·ΠΎΠ²Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ connect.

β–  Π’ Π‘Π΅Ρ€ΠΊΠ»ΠΈ-рСализациях (Π° Ρ‚Π°ΠΊΠΆΠ΅ POSIX) ΠΈΠΌΠ΅ΡŽΡ‚ΡΡ Π΄Π²Π° ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΡ… ΠΏΡ€Π°Π²ΠΈΠ»Π°, относящихся ΠΊ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ select ΠΈ Π½Π΅Π±Π»ΠΎΠΊΠΈΡ€ΡƒΠ΅ΠΌΠΎΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ connect: Π²ΠΎ-ΠΏΠ΅Ρ€Π²Ρ‹Ρ…, ΠΊΠΎΠ³Π΄Π° соСдинСниС устанавливаСтся ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎ, дСскриптор становится Π³ΠΎΡ‚ΠΎΠ²Ρ‹ΠΌ для записи [128, с. 531], ΠΈ Π²ΠΎ-Π²Ρ‚ΠΎΡ€Ρ‹Ρ…, ΠΊΠΎΠ³Π΄Π° ΠΏΡ€ΠΈ установлСнии соСдинСния встрСчаСтся ошибка, дСскриптор становится Π³ΠΎΡ‚ΠΎΠ²Ρ‹ΠΌ ΠΊΠ°ΠΊ для чтСния, Ρ‚Π°ΠΊ ΠΈ для записи [128, с. 530].

ΠŸΠ Π˜ΠœΠ•Π§ΠΠΠ˜Π•

Π­Ρ‚ΠΈ Π΄Π²Π° ΠΏΡ€Π°Π²ΠΈΠ»Π° Π² ΠΎΡ‚Π½ΠΎΡˆΠ΅Π½ΠΈΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ select Π²Ρ‹ΠΏΠ°Π΄Π°ΡŽΡ‚ ΠΈΠ· ΠΎΠ±Ρ‰Π΅Π³ΠΎ ряда Π½Π°ΡˆΠΈΡ… ΠΏΡ€Π°Π²ΠΈΠ» ΠΈΠ· Ρ€Π°Π·Π΄Π΅Π»Π° 6.3 ΠΎΡ‚Π½ΠΎΡΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ условий, ΠΏΡ€ΠΈ ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… дСскриптор становится Π³ΠΎΡ‚ΠΎΠ²Ρ‹ΠΌ для чтСния ΠΈΠ»ΠΈ записи. Π’ сокСт TCP ΠΌΠΎΠΆΠ½ΠΎ Π·Π°ΠΏΠΈΡΡ‹Π²Π°Ρ‚ΡŒ, Ссли достаточно мСста Π² Π±ΡƒΡ„Π΅Ρ€Π΅ ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΠΈ (Ρ‡Ρ‚ΠΎ всСгда Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ Π² случаС присоСдинСнного сокСта, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΌΡ‹ Π΅Ρ‰Π΅ Π½ΠΈΡ‡Π΅Π³ΠΎ Π½Π΅ записали Π² сокСт) ΠΈ сокСт являСтся присоСдинСнным (Ρ‡Ρ‚ΠΎ выполняСтся, Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΊΠΎΠ³Π΄Π° Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΎ трСхэтапноС Ρ€ΡƒΠΊΠΎΠΏΠΎΠΆΠ°Ρ‚ΠΈΠ΅). ΠŸΡ€ΠΈ Π½Π°Π»ΠΈΡ‡ΠΈΠΈ ошибки, ΠΎΠΆΠΈΠ΄Π°ΡŽΡ‰Π΅ΠΉ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ, появляСтся Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ Ρ‡ΠΈΡ‚Π°Ρ‚ΡŒ ΠΈΠ· сокСта ΠΈ Π·Π°ΠΏΠΈΡΡ‹Π²Π°Ρ‚ΡŒ Π² сокСт.

Π‘ Π½Π΅Π±Π»ΠΎΠΊΠΈΡ€ΡƒΠ΅ΠΌΡ‹ΠΌΠΈ функциями connect связано мноТСство ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌ пСрСносимости, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΌΡ‹ ΠΎΡ‚ΠΌΠ΅Ρ‚ΠΈΠΌ Π² ΠΏΠΎΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΡ… ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π°Ρ….

16.4. НСблокируСмая функция connect: ΠΊΠ»ΠΈΠ΅Π½Ρ‚ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ ΠΈ Π΄Π°Ρ‚Ρ‹

Π’ листингС 16.7 ΠΏΠΎΠΊΠ°Π·Π°Π½Π° наша функция connect_nonb, Π²Ρ‹Π·Ρ‹Π²Π°ΡŽΡ‰Π°Ρ Π½Π΅Π±Π»ΠΎΠΊΠΈΡ€ΡƒΠ΅ΠΌΡƒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ connect. ΠœΡ‹ замСняСм Π²Ρ‹Π·ΠΎΠ² Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ connect, ΠΈΠΌΠ΅ΡŽΡ‰ΠΈΠΉΡΡ Π² листингС 1.1, ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΌ Ρ„Ρ€Π°Π³ΠΌΠ΅Π½Ρ‚ΠΎΠΌ ΠΊΠΎΠ΄Π°:

if (connect_nonb(sockfd, (SA*)&servaddr, sizeof(servaddr), 0) < 0)

err_sys("connect error");

ΠŸΠ΅Ρ€Π²Ρ‹Π΅ Ρ‚Ρ€ΠΈ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚Π° ΡΠ²Π»ΡΡŽΡ‚ΡΡ ΠΎΠ±Ρ‹Ρ‡Π½Ρ‹ΠΌΠΈ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚Π°ΠΌΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ connect, Π° Ρ‡Π΅Ρ‚Π²Π΅Ρ€Ρ‚Ρ‹ΠΉ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ β€” это число сСкунд, Π² Ρ‚Π΅Ρ‡Π΅Π½ΠΈΠ΅ ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… ΠΌΡ‹ ΠΆΠ΄Π΅ΠΌ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ установлСния соСдинСния. НулСвоС Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΏΠΎΠ΄Ρ€Π°Π·ΡƒΠΌΠ΅Π²Π°Π΅Ρ‚ отсутствиС Ρ‚Π°ΠΉΠΌ- Π°ΡƒΡ‚Π° для Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ select; ΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎ, для установлСния соСдинСния TCP ядро Π±ΡƒΠ΄Π΅Ρ‚ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ свой ΠΎΠ±Ρ‹Ρ‡Π½Ρ‹ΠΉ Ρ‚Π°ΠΉΠΌ-Π°ΡƒΡ‚.

Листинг 16.7. НСблокируСмая функция connect

//lib/connect_nonb.c

 1 #include "unp.h"


 2 int

 3 connect_nonb(int sockfd, const SA *saptr, socklen_t salen, int nsec)

 4 {

 5  int flags, n, error;

 6  socklen_t len;

 7  fd_set rset, wset;

 8  struct timeval tval;


 9  flags = Fcntl(sockfd, F_GETFL, 0);

10  Fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);


11  error = 0;

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

13   if (errno != EINPROGRESS)

14    return (-1);


15  /* Пока соСдинСниС устанавливаСтся, ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ Π·Π°Π½ΡΡ‚ΡŒΡΡ Ρ‡Π΅ΠΌ-Ρ‚ΠΎ Π΄Ρ€ΡƒΠ³ΠΈΠΌ */


16  if (n == 0)

17   goto done; /* функция connect Π·Π°Π²Π΅Ρ€ΡˆΠΈΠ»Π°ΡΡŒ Π½Π΅ΠΌΠ΅Π΄Π»Π΅Π½Π½ΠΎ */


18  FD_ZERO(&rset);

19  FDSET(sockfd, &rset);

20  wset = rset;

21  tval.tv_sec = nsec;

22  tval.tv_usec = 0;


23  if ((n = Select(sockfd + 1, &rset, &wset, NULL,

24   nsec ? &tval : NULL)) == 0) {

25   close(sockfd); /* Ρ‚Π°ΠΉΠΌ-Π°ΡƒΡ‚ */

26   errno = ETIMEDOUT;

27   return (-1);

28  }

29  if (FD_ISSET(sockfd, &rset) || FD_ISSET(sockfd, &wset)) {

30   len = sizeof(error);

31   if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len) < 0)

32    return (-1); /*Π² Solaris ошибка, ΠΎΠΆΠΈΠ΄Π°ΡŽΡ‰Π°Ρ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ */

33  } else

34   err_quit("select error: sockfd not set");


35 done:

36  Fcntl(sockfd, F_SETFL, flags); /* восстанавливаСм Ρ„Π»Π°Π³ΠΈ, Π·Π°Π΄Π°ΡŽΡ‰ΠΈΠ΅ статус Ρ„Π°ΠΉΠ»Π° */


37  if (error) {

38   close(sockfd); /* Π½Π° всякий случай */

39   errno = error;

40   return (-1);

41  }

42  return (0);

43 }

Π—Π°Π΄Π°Π½ΠΈΠ΅ Π½Π΅Π±Π»ΠΎΠΊΠΈΡ€ΡƒΠ΅ΠΌΠΎΠ³ΠΎ сокСта

9-10 ΠœΡ‹ Π²Ρ‹Π·Ρ‹Π²Π°Π΅ΠΌ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ fcntl, которая Π΄Π΅Π»Π°Π΅Ρ‚ сокСт Π½Π΅Π±Π»ΠΎΠΊΠΈΡ€ΡƒΠ΅ΠΌΡ‹ΠΌ.

11-14 ΠœΡ‹ Π²Ρ‹Π·Ρ‹Π²Π°Π΅ΠΌ Π½Π΅Π±Π»ΠΎΠΊΠΈΡ€ΡƒΠ΅ΠΌΡƒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ connect. Ошибка, ΠΊΠΎΡ‚ΠΎΡ€ΡƒΡŽ ΠΌΡ‹ ΠΎΠΆΠΈΠ΄Π°Π΅ΠΌ (EINPROGRESS), ΡƒΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚ Π½Π° Ρ‚ΠΎ, Ρ‡Ρ‚ΠΎ установлСниС соСдинСния Π½Π°Ρ‡Π°Π»ΠΎΡΡŒ, Π½ΠΎ Π΅Ρ‰Π΅ Π½Π΅ Π·Π°Π²Π΅Ρ€ΡˆΠΈΠ»ΠΎΡΡŒ [128, с. 466]. Π›ΡŽΠ±Π°Ρ другая ошибка возвращаСтся Π²Ρ‹Π·Ρ‹Π²Π°ΡŽΡ‰Π΅ΠΌΡƒ процСссу.

Π’Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ Π΄Ρ€ΡƒΠ³ΠΈΡ… процСссов Π²ΠΎ врСмя установлСния соСдинСния

15 ΠΠ° этом этапС ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π΅Π»Π°Ρ‚ΡŒ всС, Ρ‡Ρ‚ΠΎ Π·Π°Ρ…ΠΎΡ‚ΠΈΠΌ, оТидая Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ установлСния соСдинСния.

ΠŸΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° Π½Π΅ΠΌΠ΅Π΄Π»Π΅Π½Π½ΠΎΠ³ΠΎ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ

16-17 Π•сли нСблокируСмая функция connect Π²ΠΎΠ·Π²Ρ€Π°Ρ‚ΠΈΠ»Π° Π½ΡƒΠ»ΡŒ, установлСниС соСдинСния Π·Π°Π²Π΅Ρ€ΡˆΠΈΠ»ΠΎΡΡŒ. Как ΠΌΡ‹ сказали, это ΠΌΠΎΠΆΠ΅Ρ‚ ΠΏΡ€ΠΎΠΈΠ·ΠΎΠΉΡ‚ΠΈ, ΠΊΠΎΠ³Π΄Π° сСрвСр находится Π½Π° Ρ‚ΠΎΠΌ ΠΆΠ΅ ΡƒΠ·Π»Π΅, Ρ‡Ρ‚ΠΎ ΠΈ ΠΊΠ»ΠΈΠ΅Π½Ρ‚.

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

18-24 ΠœΡ‹ Π²Ρ‹Π·Ρ‹Π²Π°Π΅ΠΌ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ select ΠΈ ΠΆΠ΄Π΅ΠΌ, ΠΊΠΎΠ³Π΄Π° сокСт Π±ΡƒΠ΄Π΅Ρ‚ Π³ΠΎΡ‚ΠΎΠ² Π»ΠΈΠ±ΠΎ для чтСния, Π»ΠΈΠ±ΠΎ для записи. ΠœΡ‹ обнуляСм rset, Π²ΠΊΠ»ΡŽΡ‡Π°Π΅ΠΌ Π±ΠΈΡ‚, ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΉ sockfd Π² этом Π½Π°Π±ΠΎΡ€Π΅ дСскрипторов ΠΈ Π·Π°Ρ‚Π΅ΠΌ ΠΊΠΎΠΏΠΈΡ€ΡƒΠ΅ΠΌ rset Π² wset. Π­Ρ‚ΠΎ присваиваниС, Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ, являСтся структурным присваиваниСм, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΠ±Ρ‹Ρ‡Π½ΠΎ Π½Π°Π±ΠΎΡ€Ρ‹ дСскрипторов ΠΏΡ€Π΅Π΄ΡΡ‚Π°Π²Π»ΡΡŽΡ‚ΡΡ ΠΊΠ°ΠΊ структуры. Π”Π°Π»Π΅Π΅ ΠΌΡ‹ ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·ΠΈΡ€ΡƒΠ΅ΠΌ структуру timeval ΠΈ Π·Π°Ρ‚Π΅ΠΌ Π²Ρ‹Π·Ρ‹Π²Π°Π΅ΠΌ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ select. Если Π²Ρ‹Π·Ρ‹Π²Π°ΡŽΡ‰ΠΈΠΉ процСсс Π·Π°Π΄Π°Π΅Ρ‚ Ρ‡Π΅Ρ‚Π²Π΅Ρ€Ρ‚Ρ‹ΠΉ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ Π½ΡƒΠ»Π΅Π²Ρ‹ΠΌ (Ρ‡Ρ‚ΠΎ соотвСтствуСт использованию Ρ‚Π°ΠΉΠΌ-Π°ΡƒΡ‚Π° ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ), слСдуСт Π·Π°Π΄Π°Ρ‚ΡŒ Π² качСствС послСднСго Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚Π° Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ select пустой ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ, Π° Π½Π΅ структуру timeval с Π½ΡƒΠ»Π΅Π²Ρ‹ΠΌ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ΠΌ (ΠΎΠ·Π½Π°Ρ‡Π°ΡŽΡ‰ΠΈΠΌ, Ρ‡Ρ‚ΠΎ ΠΌΡ‹ Π½Π΅ ΠΆΠ΄Π΅ΠΌ Π²ΠΎΠΎΠ±Ρ‰Π΅).

ΠžΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° Ρ‚Π°ΠΉΠΌ-Π°ΡƒΡ‚ΠΎΠ²

25-28 Π•сли функция select Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ Π½ΡƒΠ»ΡŒ, это ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ врСмя Ρ‚Π°ΠΉΠΌΠ΅Ρ€Π° истСкло, ΠΈ ΠΌΡ‹ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅ΠΌ Π²Ρ‹Π·Ρ‹Π²Π°ΡŽΡ‰Π΅ΠΌΡƒ процСссу ΠΎΡˆΠΈΠ±ΠΊΡƒ ETIMEDOUT. ΠœΡ‹ Ρ‚Π°ΠΊΠΆΠ΅ Π·Π°ΠΊΡ€Ρ‹Π²Π°Π΅ΠΌ сокСт, Ρ‡Ρ‚ΠΎΠ±Ρ‹ трСхэтапноС Ρ€ΡƒΠΊΠΎΠΏΠΎΠΆΠ°Ρ‚ΠΈΠ΅ Π½Π΅ ΠΏΡ€ΠΎΠ΄ΠΎΠ»ΠΆΠ°Π»ΠΎΡΡŒ.

ΠŸΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° возмоТности чтСния ΠΈΠ»ΠΈ записи

29-34 Π•сли дСскриптор Π³ΠΎΡ‚ΠΎΠ² для чтСния ΠΈΠ»ΠΈ для записи, ΠΌΡ‹ Π²Ρ‹Π·Ρ‹Π²Π°Π΅ΠΌ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ getsockopt, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ ΠΎΡˆΠΈΠ±ΠΊΡƒ сокСта (SO_ERROR), ΠΎΠΆΠΈΠ΄Π°ΡŽΡ‰ΡƒΡŽ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ. Если соСдинСниС Π·Π°Π²Π΅Ρ€ΡˆΠΈΠ»ΠΎΡΡŒ ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎ, это Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Π½ΡƒΠ»Π΅Π²Ρ‹ΠΌ. Если ΠΏΡ€ΠΈ установлСнии соСдинСния ΠΏΡ€ΠΎΠΈΠ·ΠΎΡˆΠ»Π° ошибка, это Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ являСтся Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ΠΌ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ errno, ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰Π΅ΠΉ ошибкС соСдинСния (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, ECONNREFUSED, ETIMEDOUT ΠΈ Ρ‚.Π΄.). ΠœΡ‹ Ρ‚Π°ΠΊΠΆΠ΅ сталкиваСмся с нашСй ΠΏΠ΅Ρ€Π²ΠΎΠΉ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠΎΠΉ пСрСносимости. Если происходит ошибка, Π‘Π΅Ρ€ΠΊΠ»ΠΈ-Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ getsockopt Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°ΡŽΡ‚ Π½ΡƒΠ»ΡŒ, Π° ошибка, ΠΎΠΆΠΈΠ΄Π°ΡŽΡ‰Π°Ρ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ, возвращаСтся Π² нашСй ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ error. Но Π² систСмС Solaris сама функция getsockopt Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ -1, Π° пСрСмСнная errno ΠΏΡ€ΠΈ этом ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅Ρ‚ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅, ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰Π΅Π΅ ошибкС, ΠΎΠΆΠΈΠ΄Π°ΡŽΡ‰Π΅ΠΉ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ. Π’ нашСм ΠΊΠΎΠ΄Π΅ ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°ΡŽΡ‚ΡΡ ΠΎΠ±Π° сцСнария.