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 — версию, работающую с программными потоками.

Поделитесь на страничке

Следующая глава >

Похожие главы из других книг

Функция SUM

Из книги Обработка баз данных на Visual Basic®.NET автора Мак-Манус Джеффри П

Функция SUM Ваши возможности в подведении итогов не ограничены простым подсчетом записей. Используя функцию SUM, можно генерировать итоговые результаты для всех возвращаемых записей по любым числовым полям. Например, для создания запроса, который генерирует итоги по


Функция uni()

Из книги Fiction Book Designer Краткое руководство автора Автор неизвестен

Функция uni() Поиск/замена символа по его юникодному номеру также может быть сделана при помощи функции uni().Пример функции uni(): Boouni(107,32)Designer найдет слово Book


Функция uni()

Из книги Fiction Book Designer 3.2. Краткое руководство автора Izekbis

Функция uni() Поиск/замена символа по его юникодному номеру также может быть сделана при помощи функции uni().Пример функции uni(): Boouni(107,32)Designer найдет слово Book


Функция not

Из книги Технология XSLT автора Валиков Алексей Николаевич


Функция contains

Из книги Fiction Book Designer 3.2. Руководство по созданию книг автора


Функция id

Из книги Введение в криптографию автора Циммерманн Филипп


Функция key

Из книги UNIX: разработка сетевых приложений автора Стивенс Уильям Ричард


Функция uni()

Из книги автора

Функция uni() Поиск/замена символа по его юникодному номеру также может быть сделана при помощи функции uni().Пример функции uni(): Boouni(107,32)Designer найдет слово Book


Хэш-функция

Из книги автора

Хэш-функция Однако описанная выше схема имеет ряд существенных недостатков. Она крайне медлительна и производит слишком большой объём данных — по меньшей мере вдвое больше объёма исходной информации. Улучшением такой схемы становится введение в процесс преобразования


5.5. Эхо-клиент TCP: функция str_cli

Из книги автора

5.5. Эхо-клиент TCP: функция str_cli Эта функция, показанная в листинге 5.4, обеспечивает отправку запроса клиента и прием ответа сервера в цикле. Функция считывает строку текста из стандартного потока ввода, отправляет ее серверу и считывает отраженный ответ сервера, после чего


6.4. Функция str_cli (продолжение)

Из книги автора

6.4. Функция str_cli (продолжение) Теперь мы можем переписать нашу функцию str_cli, представленную в разделе 5.5 (на этот раз используя функцию select), таким образом, чтобы мы получали уведомление, как только завершится процесс сервера. Проблема с предыдущей версией состояла в том,


Более простая версия функции str_cli

Из книги автора

Более простая версия функции str_cli Неблокируемая версия функции str_cli, которую мы только что показали, нетривиальна: около 135 строк кода по сравнению с 40 строками версии, использующей функцию select с блокируемым вводом-выводом (см. листинг 6.2), и 20 строками начальной версии,


Сравнение времени выполнения различных версий функции str_cli

Из книги автора

Сравнение времени выполнения различных версий функции str_cli Итак, мы продемонстрировали четыре различных версии функции str_cli. Для каждой версии мы покажем время, которое потребовалось для ее выполнения, в том числе и для версии, использующей программные потоки (см.


26.3. Использование потоков в функции str_cli

Из книги автора

26.3. Использование потоков в функции str_cli В качестве первого примера использования потоков мы перепишем нашу функцию str_cli. В листинге 16.6 была представлена версия этой функции, в которой использовалась функция fork. Напомним, что были также представлены и некоторые другие