Книга: UNIX: разработка сетевых приложений

6.7. Функция str_cli (еще раз)

6.7. Функция str_cli (еще раз)

В листинге 6.2 представлена наша обновленная (и корректная) функция str_cli. В этой версии используются функции select и shutdown. Первая уведомляет нас о том, когда сервер закрывает свой конец соединения, а вторая позволяет корректно обрабатывать пакетный ввод. Эта версия избавлена от ориентации на строки. Вместо этого она работает с буферами, что позволяет полностью избавиться от проблем, описанных в конце раздела 6.5.

Листинг 6.2. функция str_cli, использующая функцию select, которая корректно обрабатывает конец файла

//select/strcliselect02.c
 1 #include "unp.h"
 2 void
 3 str_cli(FILE *fp, int sockfd)
 4 {
 5  int maxfdp1, stdineof;
 6  fd_set rset;
 7  char buf[MAXLINE];
 8  int n;
 9  stdineof = 0;
10  FD_ZERO(&rset);
11  for (;;) {
12   if (stdineof == 0)
13    FD_SET(fileno(fp), &rset);
14   FD_SET(sockfd, &rset);
15   maxfdp1 = max(fileno(fp), sockfd) + 1;
16   Select(maxfdp1, &rset, NULL, NULL, NULL);
17   if (FD_ISSET(sockfd, &rset)) { /* сокет готов для чтения */
18    if ((n = Read(sockfd, buf, MAXLINE)) == 0) {
19     if (stdineof == 1)
20      return; /* нормальное завершение */
21     else
22      err_quit("str_cli: server terminated prematurely");
23    }
24    Write(fileno(stdout), buf, n);
25   }
26   if (FD_ISSET(fileno(fp), &rset)) { /* есть данные на входе */
27    if ((n = Read(fileno(fp), buf, MAXLINE)) == 0) {
28     stdineof = 1;
29     Shutdown(sockfd, SHUT_WR); /* отправка сегмента FIN */
30     FD_CLR(fileno(fp), &rset);
31     continue;
32    }
33    Writen(sockfd, buf, n);
34   }
35  }
36 }
5-8
 stdineof — это новый флаг, инициализируемый нулем. Пока этот флаг равен нулю, мы будем проверять готовность стандартного потока ввода к чтению с помощью функции select.

16-24 Если мы считываем на сокете признак конца файла, когда нам уже встретился ранее признак конца файла в стандартном потоке ввода, это является нормальным завершением и функция возвращает управление. Но если конец файла в стандартном потоке ввода еще не встречался, это означает, что процесс сервера завершился преждевременно. В новой версии мы вызываем функции read и write и работаем с буферами, а не со строками, благодаря чему функция select действует именно так, как мы рассчитывали.

25-33 Когда нам встречается признак конца файла на стандартном устройстве ввода, наш новый флаг stdineof устанавливается в единицу и мы вызываем функцию shutdown со вторым аргументом SHUT_WR для отправки сегмента FIN.

Если мы измерим время работы нашего клиента TCP, использующего функцию str_cli, показанную в листинге 6.2, с тем же файлом из 2000 строк, это время составит 12,3 с, что почти в 30 раз быстрее, чем при использовании версии этой функции, работающей в режиме остановки и ожидания.

Мы еще не завершили написание нашей функции str_cli: в разделе 15.2 мы разработаем ее версию с использованием неблокируемого ввода-вывода, а в разделе 23.3 — версию, работающую с программными потоками.

Оглавление книги


Генерация: 1.268. Запросов К БД/Cache: 3 / 1
поделиться
Вверх Вниз