Чтение онлайн

на главную - закладки

Жанры

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

Рис. 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)

1

Все исходные коды программ, опубликованные в этой книге, вы можете найти по адресу http://www.piter.com.

//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) мы значительно увеличили устойчивость клиента.

6.5. Пакетный ввод

К сожалению, наша функция

str_cli
все еще не вполне корректна. Сначала вернемся к ее исходной версии, приведенной в листинге 5.4. Эта функция работает в режиме остановки и ожидания (stop-and-wait mode), что удобно для интерактивного использования: функция отправляет строку серверу и затем ждет его ответа. Время ожидания складывается из одного периода обращения (RTT) и времени обработки сервером (которое близко к нулю в случае простого эхо-сервера). Следовательно, мы можем предположить, сколько времени займет отражение данного числа строк, если мы знаем время обращения (RTT) между клиентом и сервером.

Измерить RTT позволяет утилита

ping
. Если мы измерим с ее помощью время обращения к
connix.com
с нашего узла
solaris
, то средний период RTT после 30 измерений будет равен 175 мс. В [111, с. 89] показано, что это справедливо для дейтаграммы IP длиной 84 байт. Если мы возьмем первые 2000 строк файла
termcap
Solaris 2.5, то итоговый размер файла будет равен 98 349 байт, то есть в среднем 49 байт на строку. Если мы добавим размеры заголовка IP (20 байт) и заголовка TCP (20 байт), то средний сегмент TCP будет составлять 89 байт, почти как размер пакета утилиты
ping
. Следовательно, мы можем предположить, что общее время составит около 350 с для 2000 строк (2000x0,175 с). Если мы запустим наш эхо-клиент TCP из главы 5, действительное время получится около 354 с, что очень близко к нашей оценке.

Поделиться:
Популярные книги

Свадьба по приказу, или Моя непокорная княжна

Чернованова Валерия Михайловна
Любовные романы:
любовно-фантастические романы
5.57
рейтинг книги
Свадьба по приказу, или Моя непокорная княжна

Сборник коротких эротических рассказов

Коллектив авторов
Любовные романы:
эро литература
love action
7.25
рейтинг книги
Сборник коротких эротических рассказов

Отец моего жениха

Салах Алайна
Любовные романы:
современные любовные романы
7.79
рейтинг книги
Отец моего жениха

Вадбольский

Никитин Юрий Александрович
1. Вадбольский
Фантастика:
попаданцы
5.00
рейтинг книги
Вадбольский

Бастард Императора. Том 7

Орлов Андрей Юрьевич
7. Бастард Императора
Фантастика:
городское фэнтези
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Бастард Императора. Том 7

Повелитель механического легиона. Том VIII

Лисицин Евгений
8. Повелитель механического легиона
Фантастика:
технофэнтези
аниме
фэнтези
5.00
рейтинг книги
Повелитель механического легиона. Том VIII

В зоне особого внимания

Иванов Дмитрий
12. Девяностые
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
В зоне особого внимания

Таня Гроттер и магический контрабас

Емец Дмитрий Александрович
1. Таня Гроттер
Фантастика:
фэнтези
8.52
рейтинг книги
Таня Гроттер и магический контрабас

Бастард Императора. Том 2

Орлов Андрей Юрьевич
2. Бастард Императора
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Бастард Императора. Том 2

Кодекс Крови. Книга ХI

Борзых М.
11. РОС: Кодекс Крови
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Кодекс Крови. Книга ХI

Третий

INDIGO
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
Третий

Возвышение Меркурия. Книга 16

Кронос Александр
16. Меркурий
Фантастика:
попаданцы
аниме
5.00
рейтинг книги
Возвышение Меркурия. Книга 16

Идеальный мир для Лекаря 9

Сапфир Олег
9. Лекарь
Фантастика:
боевая фантастика
юмористическое фэнтези
6.00
рейтинг книги
Идеальный мир для Лекаря 9

Потусторонний. Книга 1

Погуляй Юрий Александрович
1. Господин Артемьев
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
Потусторонний. Книга 1