Протоколы TCP и UDP

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

Время чтения: 8 мин

Кратко

Секция статьи "Кратко"

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

На практике TCP используется в случаях, когда необходимо гарантировать целостность и порядок приходящих данных в ущерб скорости их передачи. Это важно для обмена файлами (например, запрос на получение файлов разметки HTML или стилей CSS). UDP используется, если скорость важнее соблюдения подобных требований (например, доставка потокового аудио или видео). Гарантий доставки и порядка получения данных нет.

Как понять

Секция статьи "Как понять"

Протоколы транспортного уровня используются для передачи данных по сети. Данные передаются в виде пакетов установленного размера. Протокол TCP (Transmission Control Protocol) формирует поток передачи данных, предварительно установив соединение. Если часть данных потеряно, то протокол автоматически повторно запрашивает утерянные данные и передаёт их от отправителя к получателю. TCP также устраняет дубликаты и информирует отправителя о результате передачи. Протокол UDP (User Datagram Protocol) не предоставляет таких гарантий, не требует установления соединения — просто пересылает пакеты с данными на адрес сетевого узла. Рассмотрим оба протокола с точки зрения взаимодействия клиента (сетевого узла, на котором работает браузер) и сервера.

Протокол TCP

Секция статьи "Протокол TCP"

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

  1. Отправитель генерирует случайное число x и передаёт его получателю в пакете SYN (от Sequence number). В этом же пакете могут указываться какие-то специальные флаги для настройки соединения.
  2. Получатель прибавляет к числу x единицу и генерирует своё число y. После этого получатель посылает отправителю числа x + 1 и y в пакете SYN ACK (от Acknowledgment Number).
  3. Завершающим этапом является передача пакета ACK отправителем с числами x + 1 и y + 1.

После рукопожатия отправитель посылает поток данных получателю. Отправитель может посылать данные сразу после посылки ACK пакета, получатель же должен подождать прихода этого пакета перед приёмом потока данных. Такой механизм рукопожатия и отправки данных обязателен для каждого соединения при общении по протоколу TCP. Пакет TCP — это блок данных, который передаётся в потоке. Порядок пакетов строго определён и не может быть нарушен.

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

Одним из решений может быть «прогрев» соединения на этапе загрузки. Когда загружается страница, можно использовать специальный атрибут rel="preconnect". Это позволит заранее установить соединение с сервером, с которого планируется загрузить ресурс, и браузер будет готов к приёму данных, когда они потребуются. Например, вот так можно заранее подготовить браузер к загрузке ресурсов с CDN:

        
          
          <link rel="dns-prefetch" href="https://example.cdn">
          <link rel="dns-prefetch" href="https://example.cdn">

        
        
          
        
      

Подробнее можно почитать в статье «Preload, prefetch and other tags». Существует и иное решение проблемы с потерей времени на установление соединения — технология TCP Fast Open. Это технология позволяет передавать данные уже на этапе передачи пакета SYN. Конечно, есть и ограничение — объём передаваемых данных. Сейчас это окно в 10 сегментов по 1460 байт, то есть 14600 байт.

Если возникла необходимость использования TCP Fast Open, необходимо настроить, что именно нужно отправлять. Это может быть критический CSS или JavaScript, а может быть и часть страницы. Браузеры на движке Chromium давно уже используют технологию Critical Rendering Path, с помощью которой браузер начинает рисовать страницу до того момента, когда получит весь HTML, CSS и JavaScript. Сейчас эту технологию поддерживает Internet Explorer, Firefox и Safari. Можно использовать Critical Rendering Path для более быстрой отрисовки страницы для пользователей этих браузеров, а это — подавляющее число пользователей.

TCP Fast Open поддерживается на уровне операционной системы (Chrome OS, Android, Linux с ядром v.4.1+, FreeBSD v.10.3+, iOS v.9+, macOS v10.11+, Windows v.10+) или браузера (Google Chrome и другие на основе Chromium, Firefox v.58+) на клиенте и на уровне операционной системы на сервере. В среднем загрузку сайта можно ускорить на 10-15%.

Протокол UDP

Секция статьи "Протокол UDP"

Центральным понятием протокола UDP является датаграмма (datagram). Это блок данных, который передаётся от отправителя к получателю без предварительной процедуры установления соединения и создания канала связи. Датаграмма — это пакет, в заголовках которого отсутствует информация:

  • Подтверждающая факт доставки пакета получателю.
  • Определяющая место пакета в изначальной последовательности данных.
  • О наличии соединения между отправителем и получателем.
  • О загруженности канала передачи данных.

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

В контексте веб-приложений UDP часто используется для передачи потоковых данных, например, аудио или видео. Каждая датаграмма состоит из небольшого набора служебных данных (информации, которая необходима для передачи датаграммы по сети) и занимает всего 8 байт.

Кажется, что в некоторых приложениях это хороший способ оптимизации трафика, но есть и проблемы при передачи датаграмм. Проблему нехватки IP-адресов решают путём отделения внутренних сетей от публичных IP-адресов сети интернет с помощью Network address translation (NAT). NAT — это специальный протокол, который при переходе из одной сети к другой подменяет сетевой адрес, сохраняя данные. Решение одной проблемы порождает другие, в частности, проблемы с передачей UDP трафика.

В заголовке датаграммы протокола UDP содержится только адрес сетевого узла, которому нужно передать данные. Часто встречаются связанные с этим коллизии, например, из-за наличия узлов с одинаковыми адресами. Трафик уходит совершенно не туда, куда должен на самом деле уходить. Это происходит во внутренних сетях компаний, в домашних сетях и других.

Ещё одной проблемой является одновременное использование TCP и UDP. Промежуточные сетевые узлы, которые обеспечивают наличие устойчивого канала для создания TCP-соединения, запоминают маршрут для прохождения пакетов. При паузе в передаче данных через протокол TCP промежуточный сетевой узел ждёт, пока не придёт пакет с нужным номером, чтобы сохранить порядок. Бывает так, что и UDP датаграммы застревают, если адрес сетевого узла получателя у TCP и UDP идентичный. Чем больше промежуточных сетевых узлов, тем чаще возникает такая проблема. Пакеты UDP могут пропасть и при переходе из одной сети в другую.

Решение указанных проблем заключается в применении вспомогательных протоколов Session Traversal Utilities for NAT (STUN) и Traversal Using Relays around NAT (TURN). STUN запоминает публичный (уникальный в сети интернет) сетевой адрес последнего узла, который стоит перед получателем. Это позволяет избежать проблем потери пакетов и переадресации их на получателя с тем же адресом. TURN позволяет установить соединение между двумя узлами NAT через промежуточный сервер. Это закрепляет путь прохождения пакетов, и они не теряются.

Сравнение TCP и UDP

Секция статьи "Сравнение TCP и UDP"

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

Характеристики TCP:

  • Надёжность передачи данных.
  • Упорядоченность данных.
  • Громоздкость процедуры пересылки данных.
  • Организация пересылки в виде потока.
  • Контроль перегрузок канала передачи данных.

UDP — протокол, который позволяет пересылать пакеты от отправителя к получателю без установления соединения.

Характеристики UDP:

  • Ненадёжность передачи.
  • Неупорядоченность данных.
  • Легковесность процедуры пересылки данных.
  • Отсутствие организации пересылки данных (использование датаграмм).
  • Отсутствие контроля перегрузок канала передачи данных.

На практике

Секция статьи "На практике"

Игорь Коровченко

Секция статьи "Игорь Коровченко"

Как можно улучшить

Секция статьи "Как можно улучшить"

Чек-лист оптимизации скорости веб-приложения передачи данных по протоколу TCP:

  • Обновите ядро сервера до последней версии.
  • Убедитесь, что размер окна (Congestion window size — cwnd) установлен на 10.
  • Убедитесь, что включено масштабирование окна.
  • Отключите медленный запуск передачи после простоя.
  • Исследуйте возможность использования технологии TCP Fast Open.
  • Устраните избыточную передачу данных.
  • Включите сжатие передаваемых данных.
  • По возможности расположите серверы ближе к пользователю, чтобы сократить время передачи данных в оба конца.
  • Повторно используйте уже установленные TCP-соединения.
  • Изучите рекомендации «Настройка TCP для HTTP».

Чек-лист оптимизации скорости веб-приложения передачи данных по протоколу UDP:

  • Протестируйте работу приложения в условиях сложных сетевых маршрутов с использованием NAT.
  • Определите и контролируйте скорость передачи данных.
  • Контролируйте перегрузку всего трафика.
  • Ограничьте скорость передачи данных той же величиной, что используется для TCP-соединений.
  • Откажитесь от счётчиков повторной передачи пакетов после потери.
  • Обрабатывайте случаи потери датаграмм, их дублирование и изменение их порядка.
  • Обрабатывайте случаи задержки доставки датаграмм.
  • Включите проверку контрольной суммы UDP в IP-протоколах обеих версий — IPv4 и IPv6.
  • Обеспечьте сохранение подключения при необходимости возобновления передачи данных.

Что почитать

Секция статьи "Что почитать"