UDP — это простой протокол транспортного уровня. Он описывается в документе RFC 768 [93]. Приложение записывает в сокет UDP
дейтаграмму(
datagram), которая
инкапсулируется(
encapsulate) или, иначе говоря, упаковывается либо в дейтаграмму IPv4, либо в дейтаграмму IPv6, и затем посылается к пункту назначения. При этом не гарантируется, что дейтаграмма UDP когда-нибудь дойдет до указанного пункта назначения.
Проблема, с которой мы сталкиваемся в процессе сетевого программирования с использованием UDP, заключается в его недостаточной надежности. Если мы хотим быть уверены в том, что дейтаграмма дошла до места назначения, мы должны встроить в наше приложение множество функций: подтверждение приема, тайм-ауты, повторные передачи и т.п.
Каждая дейтаграмма UDP имеет конкретную длину, и мы можем рассматривать дейтаграмму как
запись(
record). Если дейтаграмма корректно доходит до места назначения (то есть пакет приходит без ошибки контрольной суммы), длина дейтаграммы передается принимающему приложению. Мы уже отмечали, что TCP является
потоковым(
byte-stream) протоколом, без каких бы то ни было границ записей (см. раздел 1.2), что отличает его от UDP.
Мы также отметили, что UDP предоставляет сервис, не ориентированный на
установление соединения(
connectionless), поскольку нет необходимости в установлении долгосрочной связи между клиентом и сервером UDP. Например, клиент UDP может создать сокет и послать дейтаграмму данному серверу, а затем срезу же послать через тот же сокет дейтаграмму другому серверу. Аналогично, сервер UDP может получить пять дейтаграмм подряд через один и тот же сокет UDP от пяти различных клиентов.
2.4. TCP: протокол контроля передачи
Сервис, предоставляемый приложению протоколом TCP, отличается от сервиса, предоставляемого протоколом UDP. TCP описывается в документах RFC 793 [96], RFC 1323 [53], RFC 2581 [4], RFC 2988 [91] и RFC 3390 [2]. Прежде всего, TCP обеспечивает установление
соединений(
connections) между клиентами и серверами. Клиент TCP устанавливает соединение с выбранным сервером, обменивается с ним данными по этому соединению и затем разрывает соединение.
TCP также обеспечивает
надежность(
reliability). Когда TCP отправляет данные на другой конец соединения, он требует, чтобы ему было выслано подтверждение получения. Если подтверждение не приходит, TCP автоматически передает данные повторно и ждет в течение большего количества времени. После некоторого числа повторных передач TCP оставляет эти попытки. В среднем суммарное время попыток отправки данных занимает от 4 до 10 минут (в зависимости от реализации).
ПРИМЕЧАНИЕTCP не гарантирует получение данных адресатом, поскольку это в принципе невозможно. Если доставка оказывается невозможной, TCP уведомляет об этом пользователя, прекращая повторную передачу и разрывая соединение. Следовательно, TCP нельзя считать протоколом, надежным на 100%: он обеспечивает надежную доставку данных или надежное уведомление о неудаче.
TCP содержит алгоритмы, позволяющие динамически прогнозировать
время (период) обращения(
round-trip time, RTT) между клиентом и сервером, и таким образом определять, сколько времени необходимо для получения подтверждения. Например, RTT в локальной сети может иметь значение порядка миллисекунд, в то время как для глобальной сети (WAN) эта величина может достигать нескольких секунд. Более того, TCP постоянно пересчитывает величину RTT, поскольку она зависит от сетевого трафика.
TCP также
упорядочивает(
sequences) данные, связывая некоторый порядковый номер с каждым отправляемым им байтом. Предположим, например, что приложение записывает 2048 байт в сокет TCP, что приводит к отправке двух сегментов TCP. Первый из них содержит данные с порядковыми номерами 1-1024, второй — с номерами 1025-2048. (
Сегмент(
segment) — это блок данных, передаваемых протоколом TCP протоколу IP.) Если какой-либо сегмент приходит вне очереди (то есть если нарушается последовательность сегментов), принимающий TCP заново упорядочит сегменты, основываясь на их порядковых номерах, перед тем как отправить данные принимающему приложению. Если TCP получает дублированные данные (допустим, компьютер на другом конце ошибочно решил, что сегмент был потерян, и передал его заново, когда на самом деле он потерян не был, просто сеть была перегружена), он может определить, что данные были дублированы (исходя из порядковых номеров), и дублированные данные будут проигнорированы.