Литмир - Электронная Библиотека

Для улучшения ситуации многие реализации TCP используют отложенные подтверждения (delayed acknowledgements). Идея этого метода состоит в том, чтобы задерживать подтверждения и обновления размера окна на время до 500 мс в надежде получить дополнительные данные, вместе с которыми можно будет отправить подтверждение одним пакетом. Если терминал успеет выдать эхо в течение 500 мс, удаленной стороне нужно будет выслать только один 41-байтовый пакет, таким образом, нагрузка на сеть снизится вдвое.

Хотя отложенные подтверждения и снижают нагрузку на сеть, тем не менее эффективность использования сети отправителем, передающим множество маленьких пакетов (к примеру, 41-байтовые пакеты с 1 байтом реальных данных), продолжает оставаться невысокой. Метод, позволяющий повысить эффективность, известен как алгоритм Нагля (Nagle’s algorithm) (Nagle, 1984). Предложение Нагля звучит довольно просто: если данные поступают отправителю маленькими порциями, отправитель просто передает первый фрагмент, а остальные помещает в буфер, пока не будет получено подтверждение приема первого фрагмента. После этого можно переслать все накопленные в буфере данные в виде одного TCP-сегмента и снова начать буферизацию до получения подтверждения о доставке следующего сегмента. Таким образом, в каждый момент времени может передаваться только один маленький пакет. Если за время прохождения пакета в оба конца приложение отправляет много порций данных, алгоритм Нагля объединяет несколько таких порций в один сегмент, и, таким образом, нагрузка на сеть существенно снижается. Кроме того, согласно этому алгоритму новый пакет должен быть отправлен, если объем данных в буфере превышает максимальный размер сегмента.

Алгоритм Нагля широко применяется различными реализациями протокола TCP, однако иногда бывают ситуации, в которых его лучше отключить. В частности, интерактивным играм через Интернет обычно требуется быстрый поток маленьких пакетов с обновлениями. Если буферизировать эти данные для пакетной пересылки, игра будет работать неправильно, и пользователи будут недовольны. Более тонкая проблема заключается в том, что иногда при задержке подтверждений использование алгоритма Нагля может приводить к временным тупиковым ситуациям: получатель ждет данных, к которым можно присоединить подтверждение, а отправитель ждет подтверждения, без которого не будут переданы новые данные. Из-за этого, в частности, может задерживаться загрузка веб-страниц. На случай таких проблем существует возможность отключения алгоритма Нагля (параметр TCP_NODELAY). Подробнее об этих и других решениях см. Mogul и Minshall (2001).

Еще одна проблема, способная значительно снизить производительность протокола TCP, известна под именем синдрома глупого окна (silly window syndrome) (Clark, 1982). Суть проблемы состоит в том, что данные пересылаются TCP-подсистемой крупными блоками, но принимающая сторона интерактивного приложения считывает их посимвольно. Чтобы ситуация стала понятнее, рассмотрим рис. 6.35. Начальное состояние таково: TCP-буфер приемной стороны полон (то есть размер его окна равен 0), и отправителю это известно. Затем интерактивное приложение читает один символ из TCP-потока. Принимающая TCP-подсистема радостно сообщает отправителю, что размер окна увеличился и что он теперь может послать 1 байт. Отправитель повинуется и посылает 1 байт. Буфер снова оказывается полон, о чем получатель и извещает, посылая подтверждение для 1-байтового сегмента с нулевым размером окна. И так может продолжаться вечно.

Компьютерные сети. 5-е издание - _354.jpg

Рис. 6.35. Синдром глупого окна

Дэвид Кларк (David Clark) предложил запретить принимающей стороне отправлять информацию об однобайтовом размере окна. Вместо этого получатель должен подождать, пока в буфере не накопится значительное количество свободного места. В частности, получатель не должен отправлять сведения о новом размере окна до тех пор, пока он не сможет принять сегмент максимального размера, который он объявлял при установке соединения, или его буфер не освободился хотя бы наполовину. Кроме того, увеличению эффективности отправки может способствовать сам отправитель, отказываясь от отправки слишком маленьких сегментов. Вместо этого он должен подождать, пока размер окна не станет достаточно большим для того, чтобы можно было послать полный сегмент или, по меньшей мере, равный половине размера буфера получателя.

В задаче избавления от синдрома глупого окна алгоритм Нагля и решение Кларка дополняют друг друга. Нагль пытался решить проблему приложения, предоставляющего данные TCP-подсистеме посимвольно. Кларк старался разрешить проблему приложения, посимвольно получающего данные у TCP. Оба решения хороши и могут работать одновременно. Суть их состоит в том, чтобы не посылать и не просить передавать данные слишком малыми порциями.

Принимающая TCP-подсистема может пойти еще дальше в деле повышения производительности, просто обновляя информацию о размере окна большими порциями. Как и отправляющая TCP-подсистема, она также может буферизировать данные и блокировать запрос на чтение READ, поступающий от приложения, до тех пор, пока у нее не накопится большого объема данных. Таким образом, снижается количество обращений к TCP-подсистеме (и вместе с ними накладные расходы). Конечно, такой подход увеличивает время ожидания ответа, но для неинтерактивных приложений, например, при передаче файла, сокращение времени, затраченного на всю операцию, значительно важнее увеличения времени ожидания ответа на отдельные запросы.

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

Подтверждение может быть выслано, только если все данные вплоть до подтверждаемого байта получены. Это называется накопительным подтверждением. Если до получателя доходят сегменты 0, 1, 2, 4, 5, 6 и 7, он может подтвердить получение данных вплоть до последнего байта сегмента 2. Когда у отправителя истечет время ожидания, он передаст сегмент 3 еще раз. Если к моменту прибытия сегмента 3 получатель сохранит в буфере сегменты с 4 по 7, он сможет подтвердить получение всех байтов, вплоть до последнего байта сегмента 7.

6.5.9. Управление таймерами в TCP

В протоколе TCP используется много различных таймеров (по крайней мере, такова концепция). Наиболее важным из них является таймер повторной передачи (RTORetransmission TimeOut). Когда посылается сегмент, запускается таймер повторной передачи. Если подтверждение получения сегмента прибывает раньше, чем истекает период таймера, таймер останавливается. Если же, наоборот, период ожидания истечет раньше, чем прибудет подтверждение, сегмент передается еще раз (а таймер запускается снова). Соответственно возникает вопрос: каким должен быть интервал времени ожидания?

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

Компьютерные сети. 5-е издание - _355.jpg

Рис. 6.36. Плотность вероятности времени прибытия подтверждения: а — на канальном уровне; б — для TCP

199
{"b":"639789","o":1}