Шрифт:
В отношении второго пункта очевидно, что если соединение TCP используется для множества обменов «запрос-ответ», то стоимость установления и разрыва соединения амортизируется во всех запросах и ответах. Обычно это решение предпочтительнее, чем использование нового соединения для каждого обмена «запрос- ответ». Тем не менее существуют приложения, использующие новое соединение для каждого цикла «запрос-ответ» (например, старые версии HTTP). Кроме того, существуют приложения, в которых клиент и сервер обмениваются в одном цикле «запрос-ответ» (например, DNS), а затем могут не обращаться друг к другу в течение часов или дней.
Теперь мы перечислим функции TCP, отсутствующие в UDP. Это означает, что приложение должно само реализовывать эти функции, если они ему необходимы. Мы говорим «необходимы», потому что не все свойства требуются всем приложениям. Например, может не возникнуть необходимости повторно передавать потерянные сегменты для аудиоприложений реального времени, если приемник способен интерполировать недостающие данные. Также для простых транзакций «запрос-ответ» может не потребоваться управление потоком, если два конца соединения заранее договорятся о размерах наибольшего запроса и ответа.
Положительные подтверждения, повторная передача потерянных пакетов, обнаружение дубликатов и упорядочивание пакетов, порядок следования которых был изменен сетью. TCP подтверждает получение всех данных, позволяя обнаруживать потерянные пакеты. Реализация этих двух свойств требует, чтобы каждый сегмент данных TCP содержал порядковый номер, по которому можно впоследствии проверить получение данного сегмента. Требуется также, чтобы TCP прогнозировал значение тайм-аута повторной передачи для соединения и чтобы это значение последовательно обновлялось по мере изменения сетевого трафика между конечными точками.
Оконное управление потоком. Принимающий TCP сообщает отправляющему, какое буферное пространство он выделил для приема данных, и отправляющий не может превышать этого ограничения. То есть количество неподтвержденных данных отправителя никогда не может стать больше объявленного размера окна принимающего.
Медленный старт и предотвращение перегрузки. Это форма управления потоком, осуществляемого отправителем, служащая для определения текущей пропускной способности сети и позволяющая контролировать ситуацию во время переполнения сети. Все современные TCP-приложения должны поддерживать эти два свойства, и опыт (накопленный еще до того, как эти алгоритмы были реализованы в конце 80-х) показывает, что протоколы, не снижающие скорость передачи при перегрузке сети, лишь усугубляют эту перегрузку (см., например, [52]).
Суммируя вышесказанное, мы можем сформулировать следующие рекомендации:
UDP должениспользоваться для приложений широковещательной и многоадресной передачи. Если требуется какая-либо форма защиты от ошибок, то соответствующая функциональность должна быть добавлена клиентам и серверам. Однако приложения часто используют широковещательную и многоадресную передачу, когда некоторое (предположительно небольшое) количество ошибок вполне допустимо (например, потеря аудио- или видеопакетов). Имеются приложения многоадресной передачи, требующие надежной доставки (например, пересылка файлов при помощи многоадресной передачи), но в каждом конкретном случае мы должны решить, компенсируется ли выигрышем в производительности, получаемым за счет использования многоадресной передачи (отправка одного пакета Nполучателям вместо отправки Nкопий пакета через Nсоединений TCP), дополнительное усложнение приложения для обеспечения надежности соединений.
UDP можетиспользоваться для простых приложений «запрос-ответ», но тогда обнаружение ошибок должно быть встроено в приложение. Минимально это означает включение подтверждений, тайм-аутов и повторных передач. Управление потоком часто не является существенным для обеспечения надежности, если запросы и ответы имеют достаточно разумный размер. Мы приводим пример реализации этой функциональности в приложении UDP, представленном в разделе 22.5. Факторы, которые нужно учитывать, — это частота соединения клиента и сервера (нужно решить, можно ли не разрывать установленное соединение TCP между транзакциями) и количество данных, которыми обмениваются клиент и сервер (если в большинстве случаев при работе данного приложения требуется много пакетов, стоимость установления и разрыва соединения TCP становится менее значимым фактором).
UDP не следуетиспользовать для передачи большого количества данных (например, при передаче файлов). Причина в том, что оконное управление потоком, предотвращение переполнения и медленный старт должны быть встроены в приложение вместе с функциями, перечисленными в предыдущем пункте. Это означает, что мы фактически заново изобретаем TCP для одного конкретного приложения. Нам следует оставить производителям заботу об улучшении производительности TCP и сконцентрировать свои усилия на самом приложении.
Из этих правил есть исключения, в особенности для существующих приложений. Например, TFTP использует UDP для передачи большого количества данных. Для TFTP был выбран UDP, поскольку, во-первых, его реализация проще в отношении кода начальной загрузки (800 строк кода С для UDP в сравнении с 4500 строками для TCP, например в [128]), а во-вторых, TFTP используется только для начальной загрузки систем в локальной сети, а не для передачи большого количества данных через глобальные сети. Однако при этом требуется, чтобы в TFTP были предусмотрены такие свойства, как собственное поле порядкового номера (для подтверждений), тайм-аут и возможность повторной передачи.