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

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 строк (2000?0,175 с). Если мы запустим наш эхо-клиент TCP из главы 5, действительное время получится около 354 с, что очень близко к нашей оценке.

Если считать, что сеть между клиентом и сервером является двусторонним каналом, когда запросы идут от клиента серверу, а ответы в обратном направлении, то получится изображенный на рис. 6.8 режим остановки и ожидания.

Рис. 6.8. Временная диаграмма режима остановки и ожидания: интерактивный ввод

Запрос отправляется клиентом в нулевой момент времени, и мы предполагаем, что время обращения RTT равно 8 условным единицам. Ответ, отправленный в момент времени 4, доходит до клиента в момент времени 7. Мы также считаем, что время обработки сервером нулевое и что размер запроса равен размеру ответа. Мы показываем только пакеты данных между клиентом и сервером, игнорируя подтверждения TCP, которые также передаются по сети.

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

Чтобы понять происходящее, обратите внимание, что в пакетном режиме мы отправляем запросы так быстро, как их может принять сеть. Сервер обрабатывает их и отправляет обратно ответы с той же скоростью. Это приводит к тому, что в момент времени 7 канал целиком заполнен, как показано на рис. 6.9.

Рис. 6.9. Заполнение канала между клиентом и сервером: пакетный режим

Предполагается, что после отправки первого запроса мы немедленно посылаем другой запрос и т.д. Также предполагается, что мы можем отправлять запросы с той скоростью, с какой сеть способна их принимать, и обрабатывать ответы так быстро, как сеть их поставляет.

ПРИМЕЧАНИЕ

Существуют различные нюансы, имеющие отношение к передаче большого количества данных TCP (bulk data flow), которые мы здесь игнорируем. К ним относятся алгоритм медленного запуска (slow start algorithm), ограничивающий скорость, с которой данные отправляются на новое или незанятое соединение, и возвращаемые сегменты ACK. Все эти вопросы рассматриваются в главе 20 [111].

Чтобы увидеть, в чем заключается проблема с нашей функцией str_cli, представленной в листинге 6.1, будем считать, что файл ввода содержит только девять строк. Последняя строка отправляется в момент времени 8, как показано на рис. 6.9. Но мы не можем закрыть соединение после записи этого запроса, поскольку в канале еще есть другие запросы и ответы. Причина возникновения проблемы кроется в нашем способе обработки конца файла при вводе, когда процесс возвращается в функцию main, которая затем завершается. Но в пакетном режиме конец файла при вводе не означает, что мы закончили читать из сокета — в нем могут оставаться запросы к серверу или ответы от сервера.

Нам нужен способ закрыть одну половину соединения TCP. Другими словами, мы хотим отправить серверу сегмент FIN, тем самым сообщая ему, что закончили отправку данных, но оставляем дескриптор сокета открытым для чтения. Это делается с помощью функции shutdown, которая описывается в следующем разделе.

Вообще говоря, буферизация ввода-вывода для повышения производительности приводит к усложнению сетевых приложений (от чего пострадала и программа в листинге 6.1). Рассмотрим пример, в котором из стандартного потока ввода считывается несколько строк текста. Функция select передаст управление строке 20, в которой функция fgets считает доступные данные в буфер библиотеки stdio. Однако эта функция возвратит приложению только одну строку, а все остальные так и останутся в буфере. Считанная строка будет отправлена серверу, после чего будет снова вызвана функция select, которая будет ждать появления новых данных в стандартном потоке ввода несмотря на наличие еще не обработанных строк в буфере stdio. Причина в том, что select ничего не знает о буферах stdio и сообщает о доступности дескриптора для чтения с точки зрения системного вызова read, а не библиотечного вызова fgets. По этой причине использование fgets и select в одной программе считается опасным и требует особой осторожности.

Та же проблема связана с вызовом readline в листинге 6.1. Теперь данные скрываются от функции select уже не в буфере stdio, а в буфере readline. Вспомните, что в разделе 3.9 мы создали функцию, проверявшую состояние буфера readline. Мы могли бы воспользоваться ею перед вызовом select, чтобы проверить, нет ли в буфере readline данных, дожидающихся обработки. Наша программа усложнится еще больше, если мы допустим, что буфер readline может содержать лишь часть строки (то есть нам придется дожидаться считывания этой строки целиком).

Проблемы буферизации мы постараемся решить в усовершенствованной версии str_cli в разделе 6.7.

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

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

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

1.1.3 Ввод

Из книги C++ автора Хилл Мюррей

1.1.3 Ввод Следующая (довольно многословная) программа предлагает вам ввести число дюймов. После того, как вы это сделаете, она напечатает соответствующее число сантиметров.#include «stream.h»main() (* int inch = 0; // inch – дюйм cout «„ „inches“; cin “» inch; cout «„ inch; cout «« " in = "; cout «« inch*2.54; cout «« «


8.4 Ввод

Из книги Давайте создадим компилятор! автора Креншоу Джек

8.4 Ввод Ввод аналогичен выводу. Имеется класс istream, который предоставляет операцию »» («взять из») для небольшого мнжества стандартных типов. Функция operator»» может опредляться для типа, определяемого


Ввод/Вывод

Из книги Программирование на языке Пролог автора Клоксин У.


5.4.3. Ввод программ

Из книги AutoCAD 2009 автора Орлов Андрей Александрович

5.4.3. Ввод программ Чтение данных из файлов и запись данных в файлы наиболее полезны тогда, когда объем данных, с которыми работает наша программа и которые мы хотим поместить в базу данных, превосходит тот объем, который мы можем вводить вручную при каждом сеансе работы с


Ввод с клавиатуры

Из книги ArchiCAD 11 автора Днепров Александр Г

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


Ввод текста

Из книги Реферат, курсовая, диплом на компьютере автора Баловсяк Надежда Васильевна

Ввод текста Автотекст вставлен, продолжаем заполнение технических требований.1. Нажмите клавишу Enter. Курсор переместится в начало следующей строки.2. Введите текст первой строки. Обратите внимание, что при достижении правой границы абзаца курсор автоматически


Ввод формул

Из книги Как заработать в Интернете: Практическое пособие автора Дорохова Марта Александровна

Ввод формул Для ввода формул предназначена специальная панель инструментов Microsoft Equation, которая отображается в окне Word после запуска редактора формул. Принцип работы состоит в следующем: если необходимо ввести простую формулу, нечто вроде х + 4, вы можете просто набрать ее


Ввод дат

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

Ввод дат Печатать буквальные значения дат можно почти в любом виде, какой только возможен. Например, допустимо любое из следующих представлений:#09/1/1998##Sep 25, 93##Janua 9 1905Если редактор Visual Basic распознает введенные вами данные как допустимое значение даты, эти данные будут


19.6. IPTables — пакетный фильтр для ядер 2.4.x. и 2.6.x

Из книги Искусство программирования на языке сценариев командной оболочки автора Купер Мендель

19.6. IPTables — пакетный фильтр для ядер 2.4.x. и 2.6.x Фильтр IPTables, очень похожий на IPChains, называется так потому, что хранит цепочки правил в таблицах. Главной таблицей, в которой хранятся правила обработки всех стандартных типов трафика, является таблица filter. Именно с ней мы и будем


Пример H-1. VIEWDATA.BAT: пакетный файл DOS

Из книги Операционная система UNIX автора Робачевский Андрей М.

Пример H-1. VIEWDATA.BAT: пакетный файл DOS REM VIEWDATAREM INSPIRED BY AN EXAMPLE IN "DOS POWERTOOLS"REM BY PAUL SOMERSON@ECHO OFFIF !%1==! GOTO VIEWDATAREM IF NO COMMAND-LINE ARG...FIND "%1" C:BOZOBOOKLIST.TXTGOTO EXIT0REM PRINT LINE WITH STRING MATCH, THEN EXIT.:VIEWDATATYPE C:BOZOBOOKLIST.TXT | MOREREM SHOW ENTIRE FILE, 1 PAGE AT A TIME.:EXIT0Результат преобразования в сценарий командной


Ввод

Из книги C++ для начинающих автора Липпман Стенли

Ввод Как мы уже видели, присвоение значений переменным может осуществляться явно или с помощью вывода некоторой программы. Команда read предоставляет удобный способ присвоить переменным значения, считанные из стандартного потока ввода. Это может быть строка, введенная


20.2. Ввод

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


29.2. BPF: пакетный фильтр BSD

Из книги Священные войны мира FOSS автора Федорчук Алексей Викторович

29.2. BPF: пакетный фильтр BSD 4.4BSD и многие другие Беркли-реализации поддерживают BPF — пакетный фильтр BSD (BSD Packet Filter). Реализация BPF описана в главе 31 [128]. История BPF, описание псевдопроцессора BPF и сравнение с пакетным фильтром SunOs 4.1.x NIT приведены в [72].Каждый канальный уровень


Пакетный менеджмент

Из книги Введение в написание скриптов на Питоне для Блендера 2.5x. Примеры кода автора Larsson Thomas

Пакетный менеджмент Разговоры о репозиториях и политиках обновления повисают в воздухе без сравнения инструментария, обеспечивающего доступ к первым и реализацию вторых. Сравнением их мы сейчас и