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

Π§ΠΈΡ‚Π°Ρ‚ΡŒ ΠΎΠ½Π»Π°ΠΉΠ½ Β«ΠžΡΠ½ΠΎΠ²Ρ‹ программирования Π² LinuxΒ». Π‘Ρ‚Ρ€Π°Π½ΠΈΡ†Π° 170

Автор НСйл ΠœΡΡ‚ΡŒΡŽ

Когда select Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ΅, мноТСства дСскрипторов Π±ΡƒΠ΄ΡƒΡ‚ ΠΌΠΎΠ΄ΠΈΡ„ΠΈΡ†ΠΈΡ€ΠΎΠ²Π°Π½Ρ‹ для Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΡƒΠΊΠ°Π·Π°Ρ‚ΡŒ Π½Π° Π³ΠΎΡ‚ΠΎΠ²Ρ‹Π΅ ΠΊ Ρ‡Ρ‚Π΅Π½ΠΈΡŽ ΠΈΠ»ΠΈ записи ΠΈΠ»ΠΈ ΠΈΠΌΠ΅ΡŽΡ‰ΠΈΠ΅ ошибки дСскрипторы. Для ΠΈΡ… ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ слСдуСт ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ макрос FD_ISSET, ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡŽΡ‰ΠΈΠΉ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΡ‚ΡŒ, ΠΊΠ°ΠΊΠΈΠ΅ дСскрипторы Ρ‚Ρ€Π΅Π±ΡƒΡŽΡ‚ внимания. МоТно ΠΈΠ·ΠΌΠ΅Π½ΠΈΡ‚ΡŒ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ timeout для Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΠΎΠΊΠ°Π·Π°Ρ‚ΡŒ врСмя, ΠΎΡΡ‚Π°ΡŽΡ‰Π΅Π΅ΡΡ Π΄ΠΎ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅Π³ΠΎ ΠΏΡ€Π΅Π²Ρ‹ΡˆΠ΅Π½ΠΈΡ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ оТидания, Π½ΠΎ Ρ‚Π°ΠΊΠΎΠ΅ ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ Π½Π΅ Π·Π°Π΄Π°Π½ΠΎ стандартом X/Open. ΠŸΡ€ΠΈ ΠΏΡ€Π΅Π²Ρ‹ΡˆΠ΅Π½ΠΈΠΈ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ оТидания всС мноТСства дСскрипторов Π±ΡƒΠ΄ΡƒΡ‚ ΠΎΡ‡ΠΈΡ‰Π΅Π½Ρ‹.

Π’Ρ‹Π·ΠΎΠ² select Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ ΠΎΠ±Ρ‰Π΅Π΅ количСство дСскрипторов Π² ΠΌΠΎΠ΄ΠΈΡ„ΠΈΡ†ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹Ρ… мноТСствах. Π’ случаС сбоя ΠΎΠ½ Π²Π΅Ρ€Π½Π΅Ρ‚ -1 ΠΈ установит Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ errno, ΠΎΠΏΠΈΡΡ‹Π²Π°ΡŽΡ‰Π΅Π΅ ΠΎΡˆΠΈΠ±ΠΊΡƒ. Π’ΠΎΠ·ΠΌΠΎΠΆΠ½Ρ‹Π΅ ошибки β€” EBADF для Π½Π΅Π²Π΅Ρ€Π½Ρ‹Ρ… дСскрипторов, EINTR для Π²ΠΎΠ·Π²Ρ€Π°Ρ‚Π° ΠΈΠ·-Π·Π° прСрывания ΠΈ EINVAL для Π½Π΅ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½Ρ‹Ρ… Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠ² nfds ΠΈΠ»ΠΈ timeout.

ΠŸΡ€ΠΈΠΌΠ΅Ρ‡Π°Π½ΠΈΠ΅

НСсмотря Π½Π° Ρ‚ΠΎ, Ρ‡Ρ‚ΠΎ Linux ΠΌΠΎΠ΄ΠΈΡ„ΠΈΡ†ΠΈΡ€ΡƒΠ΅Ρ‚ структуру, Π½Π° ΠΊΠΎΡ‚ΠΎΡ€ΡƒΡŽ ΡƒΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚ timeout, фиксируя ΠΎΡΡ‚Π°Π²ΡˆΠ΅Π΅ΡΡ нСиспользованноС врСмя, Π±ΠΎΠ»ΡŒΡˆΠΈΠ½ΡΡ‚Π²ΠΎ вСрсий UNIX этого Π½Π΅ Π΄Π΅Π»Π°ΡŽΡ‚. Π‘ΠΎΠ»ΡŒΡˆΠ°Ρ Ρ‡Π°ΡΡ‚ΡŒ ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰Π΅Π³ΠΎ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½ΠΎΠ³ΠΎ ΠΊΠΎΠ΄Π°, ΠΏΡ€ΠΈΠΌΠ΅Π½ΡΡŽΡ‰Π΅Π³ΠΎ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ select, ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·ΠΈΡ€ΡƒΠ΅Ρ‚ структуру Ρ‚ΠΈΠΏΠ° timeval ΠΈ Π·Π°Ρ‚Π΅ΠΌ ΠΏΡ€ΠΎΠ΄ΠΎΠ»ΠΆΠ°Π΅Ρ‚ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π΅Π΅ Π±Π΅Π· обновлСния содСрТимого. Π’ систСмС Linux этот ΠΊΠΎΠ΄ ΠΌΠΎΠΆΠ΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒΡΡ Π½Π΅ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½ΠΎ, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ОБ Linux измСняСт структуру timeval ΠΏΡ€ΠΈ ΠΊΠ°ΠΆΠ΄ΠΎΠΌ истСчСнии ΠΎΡ‚Π²Π΅Π΄Π΅Π½Π½ΠΎΠ³ΠΎ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ оТидания. Если Π²Ρ‹ ΠΏΠΈΡˆΠ΅Ρ‚Π΅ ΠΈΠ»ΠΈ пСрСноситС ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½Ρ‹ΠΉ ΠΊΠΎΠ΄, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‰ΠΈΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ select, слСдуСт ΡƒΡ‡ΠΈΡ‚Ρ‹Π²Π°Ρ‚ΡŒ эту Ρ€Π°Π·Π½ΠΈΡ†Ρƒ ΠΈ всСгда ΠΏΠΎΠ²Ρ‚ΠΎΡ€Π½ΠΎ ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ врСмя оТидания. Π˜ΠΌΠ΅ΠΉΡ‚Π΅ Π² Π²ΠΈΠ΄Ρƒ, Ρ‡Ρ‚ΠΎ ΠΎΠ±Π° ΠΏΠΎΠ΄Ρ…ΠΎΠ΄Π° ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½Ρ‹, ΠΎΠ½ΠΈ просто Ρ€Π°Π·Π½Ρ‹Π΅!

Π’Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚Π΅ ΡƒΠΏΡ€Π°ΠΆΠ½Π΅Π½ΠΈΠ΅ 15.8.

Π£ΠΏΡ€Π°ΠΆΠ½Π΅Π½ΠΈΠ΅ 15.8. Ѐункция select

Π”Π°Π»Π΅Π΅ для дСмонстрации примСнСния Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ select ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅Π½Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° select.c. Π‘ΠΎΠ»Π΅Π΅ слоТный ΠΏΡ€ΠΈΠΌΠ΅Ρ€ Π²Ρ‹ ΡƒΠ²ΠΈΠ΄ΠΈΡ‚Π΅ Ρ‡ΡƒΡ‚ΡŒ ΠΏΠΎΠ·ΠΆΠ΅. ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° Ρ‡ΠΈΡ‚Π°Π΅Ρ‚ Π΄Π°Π½Π½Ρ‹Π΅ с ΠΊΠ»Π°Π²ΠΈΠ°Ρ‚ΡƒΡ€Ρ‹ (стандартный Π²Π²ΠΎΠ΄ β€” дСскриптор 0) со Π²Ρ€Π΅ΠΌΠ΅Π½Π΅ΠΌ оТидания 2,5 сСкунды. Π”Π°Π½Π½Ρ‹Π΅ Ρ‡ΠΈΡ‚Π°ΡŽΡ‚ΡΡ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Ρ‚ΠΎΠ³Π΄Π°, ΠΊΠΎΠ³Π΄Π° Π²Π²ΠΎΠ΄ Π³ΠΎΡ‚ΠΎΠ². ЕстСствСнно Ρ€Π°ΡΡˆΠΈΡ€ΠΈΡ‚ΡŒ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡƒ, Π²ΠΊΠ»ΡŽΡ‡ΠΈΠ² Π² зависимости ΠΎΡ‚ Ρ…Π°Ρ€Π°ΠΊΡ‚Π΅Ρ€Π° прилоТСния Π΄Ρ€ΡƒΠ³ΠΈΠ΅ дСскрипторы, Ρ‚Π°ΠΊΠΈΠ΅ ΠΊΠ°ΠΊ ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ ΠΊΠ°Π½Π°Π»Ρ‹ (serial lines) ΠΈ сокСты.

1. ΠΠ°Ρ‡Π½ΠΈΡ‚Π΅ ΠΊΠ°ΠΊ ΠΎΠ±Ρ‹Ρ‡Π½ΠΎ с Π΄ΠΈΡ€Π΅ΠΊΡ‚ΠΈΠ² include ΠΈ объявлСний, Π° Π·Π°Ρ‚Π΅ΠΌ ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·ΠΈΡ€ΡƒΠΉΡ‚Π΅ inputs для ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ Π²Π²ΠΎΠ΄Π° с ΠΊΠ»Π°Π²ΠΈΠ°Ρ‚ΡƒΡ€Ρ‹:

#include <sys/types.h>

#include <sys/time.h>

#include <stdio.h>

#include <fcntl.h>

#include <sys/ioctl.h>

#include <unistd.h>

#include <stdlib.h>

int main() {

 char buffer[128];

 int result, nread;

 fd_set inputs, testfds;

 struct timeval timeout;

 FD_ZERO(&inputs);

 FD_SET(0, &inputs);

2. ΠŸΠΎΠ΄ΠΎΠΆΠ΄ΠΈΡ‚Π΅ Π²Π²ΠΎΠ΄ ΠΈΠ· Ρ„Π°ΠΉΠ»Π° stdin Π² Ρ‚Π΅Ρ‡Π΅Π½ΠΈΠ΅ максимум 2,5 сСкунд:

 while(1) {

  testfds = inputs;

  timeout.tv_sec = 2;

  timeout.tv_usec = 500000;

  result = select(FD_SETSIZE, &testfds, (fd_set *)NULL,

   (fd_set*)NULL, &timeout);

3. Π‘пустя это врСмя ΠΏΡ€ΠΎΠ²Π΅Ρ€ΡŒΡ‚Π΅ result. Если Π²Π²ΠΎΠ΄Π° Π½Π΅ Π±Ρ‹Π»ΠΎ, ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ Ρ†ΠΈΠΊΠ» Π΅Ρ‰Π΅ Ρ€Π°Π·. Если Π² Π½Π΅ΠΌ Π²ΠΎΠ·Π½ΠΈΠΊΠ»Π° ошибка, ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° Π·Π°Π²Π΅Ρ€ΡˆΠ°Π΅Ρ‚ΡΡ:

  switch(result) {

  case 0:

   printf("timeout\n");

   break;

  case -1:

   perror("select");

   exit(1);

4. Π•сли Π²ΠΎ врСмя оТидания Ρƒ вас Π½Π°Π±Π»ΡŽΠ΄Π°ΡŽΡ‚ΡΡ Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ дСйствия, связанныС с Ρ„Π°ΠΉΠ»ΠΎΠ²Ρ‹ΠΌ дСскриптором, Ρ‡ΠΈΡ‚Π°ΠΉΡ‚Π΅ Π²Π²ΠΎΠ΄ ΠΈΠ· stdin ΠΈ Π²Ρ‹Π²ΠΎΠ΄ΠΈΡ‚Π΅ Π΅Π³ΠΎ ΠΏΡ€ΠΈ ΠΊΠ°ΠΆΠ΄ΠΎΠΌ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠΈ символа EOL (ΠΊΠΎΠ½Π΅Ρ† строки), Π΄ΠΎ Π½Π°ΠΆΠ°Ρ‚ΠΎΠΉ ΠΊΠΎΠΌΠ±ΠΈΠ½Π°Ρ†ΠΈΠΈ клавиш <Ctrl>+<D>:

  default:

   if (FD_ISSET(0, &testfds)) {

    ioctl(0, FIONREAD, &nread);

    if (nread == 0) {

     printf("keyboard done\n");

     exit(0);

    }

    nread = read(0, buffer, nread);

    buffer[nread] = 0;

    printf("read %d from keyboard: %s", nread, buffer);

   }

   break;

  }

 }

}

Π’ΠΎ врСмя выполнСния эта ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° ΠΊΠ°ΠΆΠ΄Ρ‹Π΅ Π΄Π²Π΅ с ΠΏΠΎΠ»ΠΎΠ²ΠΈΠ½ΠΎΠΉ сСкунды Π²Ρ‹Π²ΠΎΠ΄ΠΈΡ‚ строку timeout. Если Π²Ρ‹ Π½Π°Π±ΠΈΡ€Π°Π΅Ρ‚Π΅ Π΄Π°Π½Π½Ρ‹Π΅ Π½Π° ΠΊΠ»Π°Π²ΠΈΠ°Ρ‚ΡƒΡ€Π΅, ΠΎΠ½Π° Ρ‡ΠΈΡ‚Π°Π΅Ρ‚ Ρ„Π°ΠΉΠ» стандартного Π²Π²ΠΎΠ΄Π° ΠΈ ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ°Π΅Ρ‚ Ρ‚ΠΎ, Ρ‡Ρ‚ΠΎ Π±Ρ‹Π»ΠΎ Π½Π°Π±Ρ€Π°Π½ΠΎ. Π’ Π±ΠΎΠ»ΡŒΡˆΠΈΠ½ΡΡ‚Π²Π΅ ΠΊΠΎΠΌΠ°Π½Π΄Π½Ρ‹Ρ… ΠΎΠ±ΠΎΠ»ΠΎΡ‡Π΅ΠΊ Π²Π²ΠΎΠ΄ направляСтся Π² ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡƒ ΠΏΡ€ΠΈ Π½Π°ΠΆΠ°Ρ‚ΠΈΠΈ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Π΅ΠΌ клавиши <Enter> (ΠΈΠ»ΠΈ <Return>) ΠΈΠ»ΠΈ клавиш ΡƒΠΏΡ€Π°Π²Π»ΡΡŽΡ‰Π΅ΠΉ ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ, поэтому ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ°Ρ‚ΡŒ Π²Π²ΠΎΠ΄ ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ Ρ€Π°Π·, ΠΊΠΎΠ³Π΄Π° Π²Ρ‹ Π½Π°ΠΆΠΈΠΌΠ°Π΅Ρ‚Π΅ ΠΊΠ»Π°Π²ΠΈΡˆΡƒ <Enter>. Π£Ρ‡Ρ‚ΠΈΡ‚Π΅, Ρ‡Ρ‚ΠΎ сама клавиша <Enter> Ρ‚ΠΎΠΆΠ΅ читаСтся ΠΈ обрабатываСтся ΠΊΠ°ΠΊ любой Π΄Ρ€ΡƒΠ³ΠΎΠΉ символ (ΠΏΠΎΠΏΡ€ΠΎΠ±ΡƒΠΉΡ‚Π΅ Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ Π²Π²ΠΎΠ΄ Π±Π΅Π· наТатия клавиши, ввСдя ряд символов, Π·Π° ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΌΠΈ слСдуСт комбинация <Ctrl>+<D>).

$ ./select

timeout

hello

read 6 from keyboard: hello

fred

read 5 from keyboard: fred

timeout

^D

keyboard done

$

Как это Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚

ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° примСняСт Π²Ρ‹Π·ΠΎΠ² select для ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ состояния стандартного Π²Π²ΠΎΠ΄Π°. Π—Π° счСт ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚ΠΈΡ€ΠΎΠ²ΠΊΠΈ значСния Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ оТидания ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° ΠΊΠ°ΠΆΠ΄Ρ‹Π΅ 2,5 сСкунды Π²Ρ‹Π²ΠΎΠ΄ΠΈΡ‚ сообщСниС ΠΎΠ± истСчСнии Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ оТидания. О Π½Π΅ΠΌ ΡΠ²ΠΈΠ΄Π΅Ρ‚Π΅Π»ΡŒΡΡ‚Π²ΡƒΠ΅Ρ‚ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π΅Π½ΠΈΠ΅ 0 Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠ΅ΠΉ select. ΠŸΡ€ΠΈ достиТСнии ΠΊΠΎΠ½Ρ†Π° Ρ„Π°ΠΉΠ»Π° дСскриптор стандартного Π²Π²ΠΎΠ΄Π° помСчаСтся Ρ„Π»Π°Π³ΠΎΠΌ ΠΊΠ°ΠΊ Π³ΠΎΡ‚ΠΎΠ²Ρ‹ΠΉ ΠΊ Π²Π²ΠΎΠ΄Ρƒ, Π½ΠΎ ΠΏΡ€ΠΈ этом Π½Π΅Ρ‚ символов, ΠΏΡ€Π΅Π΄Π½Π°Π·Π½Π°Ρ‡Π΅Π½Π½Ρ‹Ρ… для считывания.

ΠœΠ½ΠΎΠΆΠ΅ΡΡ‚Π²Π΅Π½Π½Ρ‹Π΅ ΠΊΠ»ΠΈΠ΅Π½Ρ‚Ρ‹

Π’Π°ΡˆΠ° простая сСрвСрная ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° ΠΌΠΎΠΆΠ΅Ρ‚ Π²Ρ‹ΠΈΠ³Ρ€Π°Ρ‚ΡŒ ΠΎΡ‚ примСнСния select для ΠΎΠ΄Π½ΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ мноТСствСнных ΠΊΠ»ΠΈΠ΅Π½Ρ‚ΠΎΠ², Π½Π΅ прибСгая ΠΊ ΠΏΠΎΠΌΠΎΡ‰ΠΈ Π΄ΠΎΡ‡Π΅Ρ€Π½ΠΈΡ… процСссов. Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ этот ΠΌΠ΅Ρ‚ΠΎΠ΄ Π² Ρ€Π΅Π°Π»ΡŒΠ½Ρ‹Ρ… прилоТСниях, Π²Ρ‹ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ ΡΠ»Π΅Π΄ΠΈΡ‚ΡŒ Π·Π° Ρ‚Π΅ΠΌ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π΄Ρ€ΡƒΠ³ΠΈΠ΅ ΠΊΠ»ΠΈΠ΅Π½Ρ‚Ρ‹ Π½Π΅ ΠΆΠ΄Π°Π»ΠΈ слишком Π΄ΠΎΠ»Π³ΠΎ, ΠΏΠΎΠΊΠ° Π²Ρ‹ ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Π΅Ρ‚Π΅ ΠΏΠ΅Ρ€Π²ΠΎΠ³ΠΎ ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡ΠΈΠ²ΡˆΠ΅Π³ΠΎΡΡ ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π°.

Π‘Π΅Ρ€Π²Π΅Ρ€ ΠΌΠΎΠΆΠ΅Ρ‚ ΠΏΡ€ΠΈΠΌΠ΅Π½ΡΡ‚ΡŒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ select ΠΎΠ΄Π½ΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎ ΠΊ сокСту, ΠΎΠΆΠΈΠ΄Π°ΡŽΡ‰Π΅ΠΌΡƒ запросы Π½Π° ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅, ΠΈ ΠΊ сокСтам клиСнтских соСдинСний. Как Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π°ΠΊΡ‚ΠΈΠ²Π½ΠΎΡΡ‚ΡŒ зафиксирована, ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ макрос FD_ISSET для ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ Π² Ρ†ΠΈΠΊΠ»Π΅ всСх Π²ΠΎΠ·ΠΌΠΎΠΆΠ½Ρ‹Ρ… Ρ„Π°ΠΉΠ»ΠΎΠ²Ρ‹Ρ… дСскрипторов ΠΈ выявлСния Π°ΠΊΡ‚ΠΈΠ²Π½Ρ‹Ρ… срСди Π½ΠΈΡ….

Если сокСт, ΠΎΠΆΠΈΠ΄Π°ΡŽΡ‰ΠΈΠΉ запросов Π½Π° ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅, Π³ΠΎΡ‚ΠΎΠ² ΠΊ Π²Π²ΠΎΠ΄Ρƒ, это ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ ΠΊΠ»ΠΈΠ΅Π½Ρ‚ пытаСтся ΠΏΠΎΠ΄ΡΠΎΠ΅Π΄ΠΈΠ½ΠΈΡ‚ΡŒΡΡ, ΠΈ Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π²Ρ‹Π·Ρ‹Π²Π°Ρ‚ΡŒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ accept Π±Π΅Π· риска Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠΈ. Если клиСнтский дСскриптор ΡƒΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚ Π½Π° Π³ΠΎΡ‚ΠΎΠ²Π½ΠΎΡΡ‚ΡŒ, это ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ Π΅ΡΡ‚ΡŒ запрос ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π°, ΠΆΠ΄ΡƒΡ‰ΠΈΠΉ, Ρ‡Ρ‚ΠΎ Π²Ρ‹ смоТСтС ΠΏΡ€ΠΎΡ‡Π΅ΡΡ‚ΡŒ ΠΈ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ Π΅Π³ΠΎ. Π§Ρ‚Π΅Π½ΠΈΠ΅ 0 Π±Π°ΠΉΡ‚ΠΎΠ² ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ клиСнтский процСсс Π·Π°Π²Π΅Ρ€ΡˆΠΈΠ»ΡΡ, ΠΈ Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π·Π°ΠΊΡ€Ρ‹Ρ‚ΡŒ сокСт ΠΈ ΡƒΠ΄Π°Π»ΠΈΡ‚ΡŒ Π΅Π³ΠΎ ΠΈΠ· мноТСства своих дСскрипторов.

Π’Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚Π΅ ΡƒΠΏΡ€Π°ΠΆΠ½Π΅Π½ΠΈΠ΅ 15.9.

Π£ΠΏΡ€Π°ΠΆΠ½Π΅Π½ΠΈΠ΅ 15.9. Π£Π»ΡƒΡ‡ΡˆΠ΅Π½Π½ΠΎΠ΅ ΠΊΠ»ΠΈΠ΅Π½Ρ‚-сСрвСрноС ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅

1. Π’ Ρ„ΠΈΠ½Π°Π»ΡŒΠ½Ρ‹ΠΉ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ server5.с Π²Ρ‹ Π²ΠΊΠ»ΡŽΡ‡ΠΈΡ‚Π΅ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΎΡ‡Π½Ρ‹Π΅ Ρ„Π°ΠΉΠ»Ρ‹ sys/time.h ΠΈ sys/ioctl.h вмСсто signal.h, использованного Π² ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰Π΅ΠΉ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ΅, ΠΈ ΠΎΠ±ΡŠΡΠ²ΠΈΡ‚Π΅ нСсколько Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Ρ… ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Ρ… для Ρ€Π°Π±ΠΎΡ‚Ρ‹ с Π²Ρ‹Π·ΠΎΠ²ΠΎΠΌ select:

#include <sys/types.h>

#include <sys/socket.h>

#include <stdio.h>

#include <netinet/in.h>

#include <sys/time.h>

#include <sys/ioctl.h>

#include <unistd.h>

#include <stdlib.h>


int main() {

 int server_sockfd, client_sockfd;

 int server_len, client_len;

 struct sockaddr_in server_address;

 struct sockaddr_in client_address;

 int result;

 fd_set readfds, testfds;

2. Π‘ΠΎΠ·Π΄Π°ΠΉΡ‚Π΅ сокСт для сСрвСра ΠΈ присвойтС Π΅ΠΌΡƒ имя:

 server_sockfd = socket(AF_INET, SOCK_STREAM, 0);

 server_address.sin_family = AF_INET;

 server_address.sin_addr.s_addr = htonl(INADDR_ANY);

 server_address.sin_port = htons(9734);

 server_len = sizeof(server_address);

 bind(serversockfd, (struct sockaddr *)&server_address, server_len);

3. Π‘ΠΎΠ·Π΄Π°ΠΉΡ‚Π΅ ΠΎΡ‡Π΅Ρ€Π΅Π΄ΡŒ запросов Π½Π° соСдинСниС ΠΈ ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·ΠΈΡ€ΡƒΠΉΡ‚Π΅ мноТСство readfds для ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ Π²Π²ΠΎΠ΄Π° с сокСта server_sockfd:

 listen(server_sockfd, 5);

 FD_ZERO(&readfds);

 FD_SET(server_sockfd, &readfds);

4. Π’Π΅ΠΏΠ΅Ρ€ΡŒ ΠΆΠ΄ΠΈΡ‚Π΅ запросы ΠΎΡ‚ ΠΊΠ»ΠΈΠ΅Π½Ρ‚ΠΎΠ². ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ Π²Ρ‹ ΠΏΠ΅Ρ€Π΅Π΄Π°Π»ΠΈ пустой ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ ΠΊΠ°ΠΊ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ timeout, Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ Π½Π°ΡΡ‚ΡƒΠΏΠ°Ρ‚ΡŒ истСчСния Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ оТидания. ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° Π·Π°Π²Π΅Ρ€ΡˆΠΈΡ‚ΡΡ ΠΈ сообщит ΠΎΠ± ошибкС, Ссли select Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅, мСньшСС 1.

 while(1) {

  char ch;

  int fd;

  int nread;

  testfds = readfds;

  printf("server waiting\n");

  result = select(FD_SETSIZE, &testfds, (fd_set *)0,

   (fd_set *)0, (struct timeval *)0);

  if (result < 1) {

   perror("server5");

   exit(1);

  }

5. ΠŸΠΎΡΠ»Π΅ Ρ‚ΠΎΠ³ΠΎ ΠΊΠ°ΠΊ Π²Ρ‹ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΠ»ΠΈ, Ρ‡Ρ‚ΠΎ Π΅ΡΡ‚ΡŒ Π°ΠΊΡ‚ΠΈΠ²Π½ΠΎΡΡ‚ΡŒ, ΠΌΠΎΠΆΠ½ΠΎ Π²Ρ‹ΡΡΠ½ΠΈΡ‚ΡŒ, ΠΊΠ°ΠΊΠΎΠΉ ΠΈΠ· дСскрипторов Π°ΠΊΡ‚ΠΈΠ²Π΅Π½, провСряя ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ ΠΈΠ· Π½ΠΈΡ… ΠΏΠΎ ΠΎΡ‡Π΅Ρ€Π΅Π΄ΠΈ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ макроса FD_ISSET:

  for (fd = 0; fd < FD_SETSIZE; fd++) {

   if (FD_ISSET(fd, &testfds)) {

6. Π•сли зафиксирована Π°ΠΊΡ‚ΠΈΠ²Π½ΠΎΡΡ‚ΡŒ Π½Π° server_sockfd, это ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ запрос Π½Π° Π½ΠΎΠ²ΠΎΠ΅ соСдинСниС, ΠΈ Π²Ρ‹ добавляСтС Π² мноТСство дСскрипторов ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΉ client_sockfd:

    if (fd == server_sockfd) {

     client_len = sizeof(client_address);