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

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

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

Рис. 6.7. Условия, обрабатываемые функцией select в вызове функции str_cli

Сокет обрабатывает три условия:

1. Если протокол TCP собеседника отправляет данные, сокет становится готовым для чтения, и функция read возвращает положительное значение (то есть число байтов данных).

2. Если протокол TCP собеседника отправляет сегмент FIN (процесс завершается), сокет становится готовым для чтения, и функция read возвращает нуль (признак конца файла).

3. Если TCP собеседника отправляет RST (узел вышел из строя и перезагрузился), сокет становится готовым для чтения, и функция read возвращает -1, а переменная errno содержит код соответствующей ошибки.

В листинге 6.1[1] представлен исходный код этой версии функции.

Листинг 6.1. Реализация функции str_cli с использованием функции select (усовершенствованный вариант находится в листинге 6.2)

//select/strcliselect01.c

 1 #include "unp.h"

 2 void

 3 str_cli(FILE *fp, int sockfd)

 4 {

 5  int maxfdp1;

 6  fd_set rset;

 7  char sendline[MAXLINE], recvline[MAXLINE];

 8  FD_ZERO(&rset);

 9  for (;;) {

10   FD_SET(fileno(fp), &rset);

11   FD_SET(sockfd, &rset);

12   maxfdp1 = max(fileno(fp), sockfd) + 1;

13   Select(maxfdp1, &rset, NULL, NULL, NULL);

14   if (FD_ISSET(sockfd, &rset)) { /* сокет готов для чтения */

15    if (Readline(sockfd, recvline, MAXLINE) == 0)

16     err_quit("str_cli: server terminated prematurely");

17    Fputs(recvline, stdout);

18   }

19   if (FD_ISSET(fileno(fp), &rset)) { /* входное устройство готово для

                                           чтения */

20    if (Fgets(sendline, MAXLINE, fp) == NULL)

21     return; /* все сделано */

22    Writen(sockfd, sendline, strlen(sendline));

23   }

24  }

25 }

Вызов функции select

8-13 Нам нужен только один набор дескрипторов — для проверки готовности сокета для чтения. Этот набор дескрипторов инициализируется макросом FD_ZERO, после чего с помощью макроса FD_SET устанавливаются два бита: бит, соответствующий указателю файла fp стандартного потока ввода-вывода, и бит, соответствующий дескриптору сокета sockfd. Функция fileno преобразует указатель файла стандартного потока ввода-вывода в соответствующий ему дескриптор. Функция select (а также poll) работает только с дескрипторами.

Функция select вызывается после определения максимального из двух дескрипторов. В этом вызове указатель на набор дескрипторов для записи и указатель на набор дескрипторов с исключениями являются пустыми. Последний аргумент (ограничение по времени) также является пустым указателем, поскольку мы хотим, чтобы процесс был блокирован, пока не будут готовы данные для чтения.

Обработка сокета, готового для чтения

14-18 Если по завершении функции select сокет готов для чтения, отраженная строка считывается функцией readline и выводится функцией fputs.

Обработка ввода, допускающего возможность чтения

19-23 Если стандартный поток ввода готов для чтения, строка считывается функцией fgets и записывается в сокет с помощью функции writen.

Обратите внимание, что используются те же четыре функции ввода-вывода, что и в листинге 5.4: fgets, writen, readline и fputs, но порядок их следования внутри функции str_cli изменился. Раньше выполнение функции str_cli определялось функцией fgets, а теперь ее место заняла select. С помощью всего нескольких дополнительных строк кода (сравните листинги 6.1 и 5.4) мы значительно увеличили устойчивость клиента.

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

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

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

Продолжение объекта

Из книги AutoCAD 2009 для студента. Самоучитель автора Соколова Татьяна Юрьевна

Продолжение объекта Snap to Extension – привязка к продолжениям объектов.Она необходима в том случае, когда при построении объектов требуется использовать линии, являющиеся временным продолжением существующих линий и дуг. Данный режим можно совмещать с режимом Apparent Intersect с


19.9 Продолжение совершенствования

Из книги TCP/IP Архитектура, протоколы, реализация (включая IP версии 6 и IP Security) автора Фейт Сидни М

19.9 Продолжение совершенствования В ответ на требования пользователей по обеспечению больших функциональных возможностей HTTP и HTML постоянно совершенствуются. На момент написания книги шла разработка стандартов для обеспечения безопасности взаимодействий


1.3.4. Продолжение установки

Из книги Linux: Полное руководство автора Колисниченко Денис Николаевич

1.3.4. Продолжение установки Выберите класс установки (рис. 1.4). Рис. 1.4. Выбор класса установкиКласс «Персональный компьютер» подойдет для начинающих пользователей. Будут установлены: графический интерфейс, очень похожий на привычный рабочий стол ОС Windows, и программы,


9.1.2. Продолжение загрузки.

Из книги AutoCAD 2009. Учебный курс автора Соколова Татьяна Юрьевна

9.1.2. Продолжение загрузки. Демон initС момента загрузки ядра процесс начальной загрузки системы идет под управлением самой системы. Первой получает управление процедура автозапуска ядра. Она определяет объем доступной оперативной памяти, тип и быстродействие процессора,


Продолжение объекта

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

Продолжение объекта Snap to Extension – привязка к продолжениям объектов.Она необходима в том случае, когда при построении объектов требуется использовать линии, являющиеся временным продолжением существующих линий и дуг. Данный режим можно совмещать с режимом Apparent Intersect с


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

Из книги S. D. F. автора Cat W

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


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

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

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


6.8. Эхо-сервер TCP (продолжение)

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

6.8. Эхо-сервер TCP (продолжение) Вернемся к нашему эхо-серверу TCP из разделов 5.2 и 5.3. Перепишем сервер как одиночный процесс, который будет использовать функцию select для обработки любого числа клиентов, вместо того чтобы порождать с помощью функции fork по одному дочернему


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

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

8.12. Функция dg_cli (продолжение) Вернемся к функции dg_cli, показанной в листинге 8.4, и перепишем ее, с тем чтобы она вызывала функцию connect. В листинге 8.7 показана новая функция.Листинг 8.7. Функция dg_cli, вызывающая функцию connect//udpcliserv/dgcliconnect.c 1 #include "unp.h" 2 void 3 dg_cli(FILE *fp, int sockfd, const SA


Более простая версия функции 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. Напомним, что были также представлены и некоторые другие