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

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

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

Π’ листингС 3.8 прСдставлСна Ρ‡Π°ΡΡ‚ΡŒ исходного ΠΊΠΎΠ΄Π°, ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°ΡŽΡ‰Π°Ρ сСмСйство AF_INET.

Листинг 3.8. Наша функция sock_ntop

//lib/sock_ntop.c

 5 char *

 6 sock_ntop(const struct sockaddr *sa, socklen_t salen)

 7 {

 8  char portstr[7];

 9  static char str[128]; /* макс. Π΄Π»ΠΈΠ½Π° для Π΄ΠΎΠΌΠ΅Π½Π½ΠΎΠ³ΠΎ сокСта Unix */


10  switch (sa->sa_family) {

11  case AF_INET: {

12    struct sockaddr_in *sin = (struct sockaddr_in*)sa;


13    if (inet_ntop(AF_INET, &sin->sin_addr. str, sizeof(str)) == NULL)

14     return (NULL);

15    if (ntohs(sin->sin_port) != 0) {

16     snprintf(portstr, sizeof(portstr), ntohs(sin->sin_port));

17     strcat(str, portstr);

18    }

19    return (str);

20   }

Для Ρ€Π°Π±ΠΎΡ‚Ρ‹ со структурами адрСсов сокСтов ΠΌΡ‹ опрСдСляСм Π΅Ρ‰Π΅ нСсколько Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ упростят ΠΏΠ΅Ρ€Π΅Π½ΠΎΡΠΈΠΌΠΎΡΡ‚ΡŒ нашСго ΠΊΠΎΠ΄Π° ΠΌΠ΅ΠΆΠ΄Ρƒ IPv4 ΠΈ IPv6.

#include "unp.h"


int sock_bind_wild(int sockfd, int family);

Π’ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚: 0 Π² случаС ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎΠ³ΠΎ выполнСния Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, -1 Π² случаС ошибки


int sock_cmp_addr(const struct sockaddr *sockaddr1,

 const struct sockaddr *sockaddr2, socklen_t addrlen);

Π’ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚: 0, Ссли адрСса относятся ΠΊ ΠΎΠ΄Π½ΠΎΠΌΡƒ сСмСйству ΠΈ ΡΠΎΠ²ΠΏΠ°Π΄Π°ΡŽΡ‚, Π½Π΅Π½ΡƒΠ»Π΅Π²ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ Π² ΠΏΡ€ΠΎΡ‚ΠΈΠ²Π½ΠΎΠΌ случаС


int sock_cmp_port(const struct sockaddr *sockaddr1,

 const struct sockaddr *sockaddr2, socklen_t addrlen);

Π’ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚: 0, Ссли адрСса относятся ΠΊ ΠΎΠ΄Π½ΠΎΠΌΡƒ сСмСйству ΠΈ ΠΏΠΎΡ€Ρ‚Ρ‹ ΡΠΎΠ²ΠΏΠ°Π΄Π°ΡŽΡ‚, Π½Π΅Π½ΡƒΠ»Π΅Π²ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ Π² ΠΏΡ€ΠΎΡ‚ΠΈΠ²Π½ΠΎΠΌ случаС


int sock_get_port(const struct sockaddr *sockaddr, socklen_t addrlen);

Π’ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚: Π½Π΅ΠΎΡ‚Ρ€ΠΈΡ†Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹ΠΉ Π½ΠΎΠΌΠ΅Ρ€ ΠΏΠΎΡ€Ρ‚Π° для адрСсов IPv4 ΠΈΠ»ΠΈ IPv6, ΠΈΠ½Π°Ρ‡Π΅ -1


char *sock_ntop_host(const struct sockaddr *sockaddr, socklen_t addrlen);

Π’ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚: нСпустой ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ Π² случаС ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎΠ³ΠΎ выполнСния Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, NULL Π² случаС ошибки


void sock_set_addr(const struct sockaddr *sockaddr,

 socklen_t addrlen, void *ptr);

void sock_set_port(const struct sockaddr *sockaddr,

 socklen_t addrlen, int port);

void sock_set_wild(struct sockaddr *sockaddr, socklen_t addrlen);

Ѐункция sock_bind_wild связываСт ΡƒΠ½ΠΈΠ²Π΅Ρ€ΡΠ°Π»ΡŒΠ½Ρ‹ΠΉ адрСс ΠΈ динамичСски Π½Π°Π·Π½Π°Ρ‡Π°Π΅ΠΌΡ‹ΠΉ ΠΏΠΎΡ€Ρ‚ с сокСтом. Ѐункция sock_cmp_addr сравниваСт адрСсныС части Π΄Π²ΡƒΡ… структур адрСса сокСта, Π° функция sock_cmp_port сравниваСт Π½ΠΎΠΌΠ΅Ρ€Π° ΠΈΡ… ΠΏΠΎΡ€Ρ‚ΠΎΠ². Ѐункция sock_get_port Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π½ΠΎΠΌΠ΅Ρ€ ΠΏΠΎΡ€Ρ‚Π°, Π° функция sock_ntop_host ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΡƒΠ΅Ρ‚ ΠΊ Ρ„ΠΎΡ€ΠΌΠ°Ρ‚Ρƒ прСдставлСния Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Ρ‚Ρƒ Ρ‡Π°ΡΡ‚ΡŒ структуры адрСса сокСта, которая относится ΠΊ ΡƒΠ·Π»Ρƒ (всС, ΠΊΡ€ΠΎΠΌΠ΅ ΠΏΠΎΡ€Ρ‚Π°, Ρ‚ΠΎ Π΅ΡΡ‚ΡŒ IP-адрСс ΡƒΠ·Π»Π°). Ѐункция sock_set_addr присваиваСт адрСсной части структуры Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅, ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠ΅ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ΠΎΠΌ ptr, Π° функция sock_set_port Π·Π°Π΄Π°Π΅Ρ‚ Π² структурС адрСса сокСта Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π½ΠΎΠΌΠ΅Ρ€ ΠΏΠΎΡ€Ρ‚Π°. Ѐункция sock_set_wild Π·Π°Π΄Π°Π΅Ρ‚ Π°Π΄Ρ€Π΅ΡΠ½ΡƒΡŽ Ρ‡Π°ΡΡ‚ΡŒ структуры Ρ‡Π΅Ρ€Π΅Π· символы подстановки. Как ΠΎΠ±Ρ‹Ρ‡Π½ΠΎ, ΠΌΡ‹ прСдоставляСм для всСх этих Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ- ΠΎΠ±Π΅Ρ€Ρ‚ΠΊΠΈ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°ΡŽΡ‚ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅, ΠΎΡ‚Π»ΠΈΡ‡Π½ΠΎΠ΅ ΠΎΡ‚ Ρ‚ΠΈΠΏΠ° void, ΠΈ Π² Π½Π°ΡˆΠΈΡ… ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ°Ρ… ΠΎΠ±Ρ‹Ρ‡Π½ΠΎ Π²Ρ‹Π·Ρ‹Π²Π°Π΅ΠΌ ΠΈΠΌΠ΅Π½Π½ΠΎ ΠΎΠ±Π΅Ρ€Ρ‚ΠΊΠΈ. ΠœΡ‹ Π½Π΅ ΠΏΡ€ΠΈΠ²ΠΎΠ΄ΠΈΠΌ Π² Π΄Π°Π½Π½ΠΎΠΉ ΠΊΠ½ΠΈΠ³Π΅ исходный ΠΊΠΎΠ΄ для этих Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ, Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ ΠΎΠ½ свободно доступСн (см. прСдисловиС).

3.9. Π€ΡƒΠ½ΠΊΡ†ΠΈΠΈ readn, writen ΠΈ readline

ΠŸΠΎΡ‚ΠΎΠΊΠΎΠ²Ρ‹Π΅ сокСты (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, сокСты TCP) Π΄Π΅ΠΌΠΎΠ½ΡΡ‚Ρ€ΠΈΡ€ΡƒΡŽΡ‚ с функциями read ΠΈ write ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅, ΠΎΡ‚Π»ΠΈΡ‡Π½ΠΎΠ΅ ΠΎΡ‚ ΠΎΠ±Ρ‹Ρ‡Π½ΠΎΠ³ΠΎ Π²Π²ΠΎΠ΄Π°-Π²Ρ‹Π²ΠΎΠ΄Π° Ρ„Π°ΠΉΠ»ΠΎΠ². Ѐункция read ΠΈΠ»ΠΈ write Π½Π° ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ²ΠΎΠΌ сокСтС ΠΌΠΎΠΆΠ΅Ρ‚ ввСсти ΠΈΠ»ΠΈ вывСсти Π½Π΅ΠΌΠ½ΠΎΠ³ΠΎ мСньшС Π±Π°ΠΉΡ‚ΠΎΠ², Ρ‡Π΅ΠΌ Π·Π°ΠΏΡ€Π°ΡˆΠΈΠ²Π°Π»ΠΎΡΡŒ, Π½ΠΎ это Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ ошибкой. ΠŸΡ€ΠΈΡ‡ΠΈΠ½ΠΎΠΉ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ достиТСниС Π³Ρ€Π°Π½ΠΈΡ† Π±ΡƒΡ„Π΅Ρ€Π° для сокСта Π² ядрС. ВсС, Ρ‡Ρ‚ΠΎ трСбуСтся Π² этой ситуации β€” Ρ‡Ρ‚ΠΎΠ±Ρ‹ процСсс ΠΏΠΎΠ²Ρ‚ΠΎΡ€ΠΈΠ» Π²Ρ‹Π·ΠΎΠ² Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ read ΠΈΠ»ΠΈ write для Π²Π²ΠΎΠ΄Π° ΠΈΠ»ΠΈ Π²Ρ‹Π²ΠΎΠ΄Π° ΠΎΡΡ‚Π°Π²ΡˆΠΈΡ…ΡΡ Π±Π°ΠΉΡ‚ΠΎΠ². (НСкоторыС вСрсии Unix Π²Π΅Π΄ΡƒΡ‚ сСбя Π°Π½Π°Π»ΠΎΠ³ΠΈΡ‡Π½ΠΎ ΠΏΡ€ΠΈ записи Π² ΠΊΠ°Π½Π°Π» (pipe) Π±ΠΎΠ»Π΅Π΅ 4096 Π±Π°ΠΉΡ‚.) Π­Ρ‚ΠΎΡ‚ сцСнарий всСгда Π²ΠΎΠ·ΠΌΠΎΠΆΠ΅Π½ Π½Π° ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ²ΠΎΠΌ сокСтС ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ read, Π½ΠΎ с Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠ΅ΠΉ write ΠΎΠ½ ΠΎΠ±Ρ‹Ρ‡Π½ΠΎ Π½Π°Π±Π»ΡŽΠ΄Π°Π΅Ρ‚ΡΡ, Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Ссли сокСт Π½Π΅Π±Π»ΠΎΠΊΠΈΡ€ΡƒΠ΅ΠΌΡ‹ΠΉ. Π’Π΅ΠΌ Π½Π΅ ΠΌΠ΅Π½Π΅Π΅ вмСсто write ΠΌΡ‹ всСгда Π²Ρ‹Π·Ρ‹Π²Π°Π΅ΠΌ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ writen Π½Π° Ρ‚ΠΎΡ‚ случай, Ссли Π² Π΄Π°Π½Π½ΠΎΠΉ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π΅Π½ΠΈΠ΅ мСньшСго количСства Π΄Π°Π½Π½Ρ‹Ρ…, Ρ‡Π΅ΠΌ ΠΌΡ‹ Π·Π°ΠΏΡ€Π°ΡˆΠΈΠ²Π°Π΅ΠΌ.

Π’Π²Π΅Π΄Π΅ΠΌ Ρ‚Ρ€ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ для чтСния ΠΈ записи Π² ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ²Ρ‹ΠΉ сокСт.

#include "unp.h"


ssize_t readn(int filedes, void *buff, size_t nbytes);

ssize_t writen(int filedes, const void *buff, size_t nbytes);

ssize_t readline(int filedes, void *buff, size_t maxlen);

ВсС Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°ΡŽΡ‚: количСство считанных ΠΈΠ»ΠΈ записанных Π±Π°ΠΉΡ‚ΠΎΠ², -1 Π² случаС ошибки

Π’ листингС 3.9 прСдставлСна функция readn, Π² листингС 3.10 β€” функция writen, Π° Π² листингС 3.11 β€” функция readline.

Листинг 3.9. Ѐункция readn: считываниС n Π±Π°ΠΉΡ‚ ΠΈΠ· дСскриптора

//lib/readn.c

 1 #include "unp.h"


 2 ssize_t /* Π‘Ρ‡ΠΈΡ‚Ρ‹Π²Π°Π΅Ρ‚ n Π±Π°ΠΉΡ‚ ΠΈΠ· дСскриптора */

 3 readn(int fd, void *vptr, size_t n)

 4 {

 5  size_t nleft;

 6  ssize_t nread;

 7  char *ptr;


 8  ptr = vptr;

 9  nleft = n;

10  while (nleft > 0) {

11   if ((nread = read(fd, ptr, nleft)) < 0) {

12    if (errno == EINTR)

13     nread = 0; /* ΠΈ Π²Ρ‹Π·Ρ‹Π²Π°Π΅Ρ‚ снова Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ read() */

14    else

15     return (-1);

16   } else if (nread == 0)

17   break; /* EOF */


18   nleft -= nread;

19   ptr += nread;

20  }

21  return (n - nleft); /* Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ >= 0 */

22 }

Листинг 3.10. Ѐункция writen: запись n Π±Π°ΠΉΡ‚ Π² дСскриптор

//lib/writen.c

 1 #include "unp.h"


 2 ssize_t /* ЗаписываСт n Π±Π°ΠΉΡ‚ Π² дСскриптор */

 3 writen(int fd, const void *vptr, size_t n)

 4 {

 5  size_t nleft;

 6  ssize_t nwritten;

 7  const char *ptr;


 8  ptr = vptr;

 9  nleft = n;

10  while (nleft > 0) {

11   if ((nwritten = write(fd, ptr, nleft)) <= 0) {

12    if (errno == EINTR)

13     nwritten = 0; /* ΠΈ снова Π²Ρ‹Π·Ρ‹Π²Π°Π΅Ρ‚ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ write() */

14    else

15     return (-1); /* ошибка */

16   }

17   nleft -= nwritten;

18   ptr += nwritten;

19  }

20  return (n);

21 }

Листинг 3.11. Ѐункция readline: считываниС ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΉ строки ΠΈΠ· дСскриптора, ΠΏΠΎ ΠΎΠ΄Π½ΠΎΠΌΡƒ Π±Π°ΠΉΡ‚Ρƒ Π·Π° ΠΎΠ΄ΠΈΠ½ Ρ€Π°Π·

//test/readline1.с

 1 #include "unp.h"

   /* УТасно мСдлСнная вСрсия, приводится Ρ‚ΠΎΠ»ΡŒΠΊΠΎ для ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π° */


 2 ssize_t

 3 readline(int fd, void *vptr, size_t maxlen)

 4 {

 5  ssize_t n, rc;

 6  char c, *ptr;


 7  ptr = vptr;

 8  for (n = 1; n < maxlen; n++) {

 9   again:

10   if ((rc = read(fd, &c, 1)) == 1) {

11    *ptr++ = c;

12    if (c == '\n')

13     break; /* записан символ Π½ΠΎΠ²ΠΎΠΉ строки, ΠΊΠ°ΠΊ Π² fgets() */

14   } else if (rc == 0) {

15    if (n == 1)

16     return (0); /* EOF, Π΄Π°Π½Π½Ρ‹Π΅ Π½Π΅ считаны */

17    else

18     break; /* EOF, Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π΄Π°Π½Π½Ρ‹Π΅ Π±Ρ‹Π»ΠΈ считаны */

19   } else {

20    if (errno == EINTR)

21     goto again;

22    return (-1); /* ошибка, errno задаСтся Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠ΅ΠΉ read() */

23   }

24  }


25  *ptr = 0; /* Π·Π°Π²Π΅Ρ€ΡˆΠ°Π΅ΠΌ Π½ΡƒΠ»Π΅ΠΌ, ΠΊΠ°ΠΊ Π² fgets() */

26  return (n);

27 }

Если функция чтСния ΠΈΠ»ΠΈ записи (read ΠΈΠ»ΠΈ write) Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ ΠΎΡˆΠΈΠ±ΠΊΡƒ, Ρ‚ΠΎ наши Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΡΡŽΡ‚, Π½Π΅ совпадаСт Π»ΠΈ ΠΊΠΎΠ΄ ошибки с EINTR (ΠΏΡ€Π΅Ρ€Ρ‹Π²Π°Π½ΠΈΠ΅ систСмного Π²Ρ‹Π·ΠΎΠ²Π° сигналом, см. Ρ€Π°Π·Π΄Π΅Π» 5.9). Π’ этом случаС прСрванная функция вызываСтся ΠΏΠΎΠ²Ρ‚ΠΎΡ€Π½ΠΎ. ΠœΡ‹ ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Π΅ΠΌ ΠΎΡˆΠΈΠ±ΠΊΡƒ Π² этой Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π½Π΅ Π·Π°ΡΡ‚Π°Π²Π»ΡΡ‚ΡŒ процСсс снова Π²Ρ‹Π·Π²Π°Ρ‚ΡŒ read ΠΈΠ»ΠΈ write, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ Ρ†Π΅Π»ΡŒΡŽ Π½Π°ΡˆΠΈΡ… Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ являСтся ΠΏΡ€Π΅Π΄ΠΎΡ‚Π²Ρ€Π°Ρ‰Π΅Π½ΠΈΠ΅ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ Π½Π΅Ρ…Π²Π°Ρ‚ΠΊΠΈ Π΄Π°Π½Π½Ρ‹Ρ… Π²Ρ‹Π·Ρ‹Π²Π°ΡŽΡ‰ΠΈΠΌ процСссом.

Π’ Ρ€Π°Π·Π΄Π΅Π»Π΅ 14.3 ΠΌΡ‹ ΠΏΠΎΠΊΠ°ΠΆΠ΅ΠΌ, Ρ‡Ρ‚ΠΎ Π²Ρ‹Π·ΠΎΠ² Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ recv с Ρ„Π»Π°Π³ΠΎΠΌ MSG_WAITALL позволяСт ΠΎΠ±ΠΎΠΉΡ‚ΠΈΡΡŒ Π±Π΅Π· использования ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ readn.

Π—Π°ΠΌΠ΅Ρ‚ΠΈΠΌ, Ρ‡Ρ‚ΠΎ наша функция readline Π²Ρ‹Π·Ρ‹Π²Π°Π΅Ρ‚ ΡΠΈΡΡ‚Π΅ΠΌΠ½ΡƒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ read ΠΎΠ΄ΠΈΠ½ Ρ€Π°Π· для ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ Π±Π°ΠΉΡ‚Π° Π΄Π°Π½Π½Ρ‹Ρ…. Π­Ρ‚ΠΎ ΠΎΡ‡Π΅Π½ΡŒ нСэффСктивно, поэтому ΠΌΡ‹ ΠΈ написали Π² ΠΏΡ€ΠΈΠΌΠ΅Ρ‡Π°Π½ΠΈΠΈ «УТасно ΠΌΠ΅Π΄Π»Π΅Π½Π½ΠΎ!Β». Π’ΠΎΠ·Π½ΠΈΠΊΠ°Π΅Ρ‚ соблазн ΠΎΠ±Ρ€Π°Ρ‚ΠΈΡ‚ΡŒΡΡ ΠΊ стандартной Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ΅ Π²Π²ΠΎΠ΄Π°-Π²Ρ‹Π²ΠΎΠ΄Π° (stdio). Об этом ΠΌΡ‹ ΠΏΠΎΠ³ΠΎΠ²ΠΎΡ€ΠΈΠΌ Ρ‡Π΅Ρ€Π΅Π· Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ врСмя Π² Ρ€Π°Π·Π΄Π΅Π»Π΅ 14.8, Π½ΠΎ ΡƒΡ‡Ρ‚ΠΈΡ‚Π΅, Ρ‡Ρ‚ΠΎ это ΠΌΠΎΠΆΠ΅Ρ‚ привСсти ΠΊ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½Ρ‹ΠΌ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ°ΠΌ. БуфСризация, прСдоставляСмая stdio, Ρ€Π΅ΡˆΠ°Π΅Ρ‚ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹ с ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒΡŽ, Π½ΠΎ ΠΏΡ€ΠΈ этом создаСт мноТСство логистичСских слоТностСй, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π² свою ΠΎΡ‡Π΅Ρ€Π΅Π΄ΡŒ ΠΏΠΎΡ€ΠΎΠΆΠ΄Π°ΡŽΡ‚ скрытыС ошибки Π² ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΈ. Π”Π΅Π»ΠΎ Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ состояниС Π±ΡƒΡ„Π΅Ρ€ΠΎΠ² stdio нСдоступно процСссу. Рассмотрим, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, строчный ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ» взаимодСйствия ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π° ΠΈ сСрвСра, ΠΏΡ€ΠΈΡ‡Π΅ΠΌ Ρ‚Π°ΠΊΠΎΠΉ, Ρ‡Ρ‚ΠΎ ΠΌΠΎΠ³ΡƒΡ‚ ΡΡƒΡ‰Π΅ΡΡ‚Π²ΠΎΠ²Π°Ρ‚ΡŒ Ρ€Π°Π·Π½Ρ‹Π΅ нСзависимыС Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ ΠΊΠ»ΠΈΠ΅Π½Ρ‚ΠΎΠ² ΠΈ сСрвСров (достаточно Ρ‚ΠΈΠΏΠΈΡ‡Π½ΠΎΠ΅ явлСниС; Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, мноТСство Π²Π΅Π±-Π±Ρ€Π°ΡƒΠ·Π΅Ρ€ΠΎΠ² ΠΈ Π²Π΅Π±-сСрвСров Π±Ρ‹Π»ΠΈ Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Π°Π½Ρ‹ нСзависимо Π² соотвСтствии со спСцификациСй HTTP). Π₯ΠΎΡ€ΠΎΡˆΠΈΠΉ ΡΡ‚ΠΈΠ»ΡŒ программирования Π·Π°ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ΡΡ Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ эти ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ Π½Π΅ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΎΠΆΠΈΠ΄Π°Ρ‚ΡŒ ΠΎΡ‚ своих собСсСдников соблюдСния Ρ‚ΠΎΠ³ΠΎ ΠΆΠ΅ ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»Π°, Π½ΠΎ ΠΈ ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Ρ‚Ρ€Π°Ρ„ΠΈΠΊ Π½Π° Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ получСния Π½Π΅ΠΏΡ€Π΅Π΄Π²ΠΈΠ΄Π΅Π½Π½ΠΎΠ³ΠΎ Ρ‚Ρ€Π°Ρ„ΠΈΠΊΠ°. ΠŸΠΎΠ΄ΠΎΠ±Π½Ρ‹Π΅ Π½Π°Ρ€ΡƒΡˆΠ΅Π½ΠΈΡ ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»Π° Π΄ΠΎΠ»ΠΆΠ½Ρ‹ Ρ€Π°ΡΡΠΌΠ°Ρ‚Ρ€ΠΈΠ²Π°Ρ‚ΡŒΡΡ ΠΊΠ°ΠΊ ошибки, Ρ‡Ρ‚ΠΎΠ±Ρ‹ программисты ΠΈΠΌΠ΅Π»ΠΈ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ Π½Π°Ρ…ΠΎΠ΄ΠΈΡ‚ΡŒ ΠΈ ΡƒΡΡ‚Ρ€Π°Π½ΡΡ‚ΡŒ Π½Π΅ΠΏΠΎΠ»Π°Π΄ΠΊΠΈ Π² ΠΊΠΎΠ΄Π΅, Π° Ρ‚Π°ΠΊΠΆΠ΅ ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠΈΠ²Π°Ρ‚ΡŒ ΠΏΠΎΠΏΡ‹Ρ‚ΠΊΠΈ Π²Π·Π»ΠΎΠΌΠ° систСм. ΠžΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° Π½Π΅ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½ΠΎΠ³ΠΎ Ρ‚Ρ€Π°Ρ„ΠΈΠΊΠ° Π΄ΠΎΠ»ΠΆΠ½Π° Π΄Π°Π²Π°Ρ‚ΡŒ ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡŽ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ ΠΏΡ€ΠΎΠ΄ΠΎΠ»ΠΆΠ°Ρ‚ΡŒ Ρ€Π°Π±ΠΎΡ‚Ρƒ. БуфСризация stdio ΠΌΠ΅ΡˆΠ°Π΅Ρ‚ Π΄ΠΎΡΡ‚ΠΈΠΆΠ΅Π½ΠΈΡŽ пСрСчислСнных Ρ†Π΅Π»Π΅ΠΉ, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ‚ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΈΡ‚ΡŒ Π½Π°Π»ΠΈΡ‡ΠΈΠ΅ Π½Π΅ΠΏΡ€Π΅Π΄Π²ΠΈΠ΄Π΅Π½Π½Ρ‹Ρ… (Π½Π΅ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½Ρ‹Ρ…) Π΄Π°Π½Π½Ρ‹Ρ… Π² Π±ΡƒΡ„Π΅Ρ€Π°Ρ… stdio Π² любой ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½Ρ‹ΠΉ ΠΌΠΎΠΌΠ΅Π½Ρ‚.