Вот она: "C каких пор протокол TCP гарантирует доставку пакетов?"
Давайте разберемся. Честно ответьте на вопрос: а гарантирует ли TCP доставку пакетов? Все, кто ответил "да", станьте справа, те кто ответил "нет" (или "нет, но...") - слева.
Ребята слева, вы можете пока расходиться, с вами нам еще предстоит провести множество славных часов, ковыряясь в коде, играя в крокодила и контакт или просто за чашкой хорошего чая.
Ребята справа (те, кто ответил "да, гарантирует"), эта встреча у нас, увы, последняя. Возможно наши дороги еще пересекутся, но сегодня нам явно не по пути. Напоследок, давайте разберемся.
Я разделил наши "разбирательства" на три этапа:
Этап первый: философский.
Я не буду приводить сейчас общечеловеческих и философских соображений о том, что дом выстроенный на зыбком фундаменте может пошатываться, а один протокол базирующийся на другом протоколе не предоставляющем гарантий доставки (IP), сам не будет гарантировать ровным счетом ничего.
Этап второй: переводческий.
Будем прагматичны, обратимся к RFC.
В частности к RFC1122. Для начала я захотел понять, откуда же взялось выражение "гарантирует доставку" и произвел поиск по включению "guar". Итак, слово "guarantees" встречается в документе:
1. В разделе "1.1.3 Internet Protocol Suite" (1.1.3 Стек протоколов Internet) в описании Internet Layer, где говорится о том, что протокол IP не гарантирует доставки пакета.
2. В разделе "3.3.1.4 Dead Gateway Detection" (3.3.1.4 Обнаружение мертвых шлюзов), где говорится о том, что успешный пинг гарантирует то, что адресный интерфейс и сама машина включена, но не гарантирует того, что она будет выполнять роль шлюза.
3. В разделе "4.1.1 USER DATAGRAM PROTOCOL - UDP (INTRODUCTION)", где говорится что протокол UDP не гарантирует доставку дейтаграмм и практически предоставляет приложениям прямой доступ к протоколу IP.
На этом "гарантии" упомянутые в RFC заканчиваются. Т.е. мы понимаем, что в оригинальном документе нам никто ничего не гарантирует. Значит? Обратимся к переводу. Не уверен, существуют ли какие-то "праведные" переводы RFC (вроде Муравьевского перевода Толкиена или Маршаковского Бернса), но нам подойдет первый же выдаваемый Яндексом с сайта rfc.com.ru: RFC1122 на русском.
Поступим аналогичным образом, поищем включения "гаран". Слово "гарантированной" (и подобные), встречаются примерно в тех же местах, где и в английской версии плюс еще кое-где. Давайте посмотим эти отличающиеся моменты.
Первый раз мы сталкиваемся в том же разделе 1.1.3, но на один пункт раньше, на транспортном уровне:
TCP представляет собой основанный на соединениях (connection-oriented) транспортный сервис с гарантированной доставкой пакетов, обеспечивающий надежную доставку с сохранением порядка пакетов и управлением потоком данных.Протокол UDP не использует соединений (connectionless) и передает данные в виде дейтаграмм (datagram) без гарантии доставки.Этот же абзац в английской версии выглядит так:
TCP is a reliable connection-oriented transport service that provides end-to-end reliability, resequencing, and flow control. UDP is a connectionless ("datagram") transport service.Уважаемый Drop-bear и здравая логика буквально переводят это так:
TCP это надежная модель обмена данными от точки к точке с повторным упорядочиванием и управлением. UDP это модель обмена данными без установки соединения (дейтаграммами).Заметьте, никаких гарантий.
Второе упоминание (про настройку параметров и их загрузку я опустил) мы встречаем в разделе 4.2.1 (Протокол управления передачей TCP - Введение):
Протокол управления передачей - TCP (Transmission Control Protocol) [TCP:1] представляет собой транспортный протокол стека Internet для работы с виртуальными соединениями. TCP обеспечивает гарантированную доставку с сохранением порядка для полнодуплексных потоков данных (октеты или байты).Протокол TCP используется теми приложениями, которым нужен ориентированный на соединения транспортный сервис с гарантией доставки (например, электронная почта SMTP, передача файлов по протоколу FTP, служба виртуальных терминалов Telnet); требования к таким протоколам прикладного уровня описаны в работе [INTRO:1].
Английский текст:
The Transmission Control Protocol TCP [TCP:1] is the primary virtual-circuit transport protocol for the Internet suite. TCP provides reliable, in-sequence delivery of a full-duplex stream of octets (8-bit bytes). TCP is used by those applications needing reliable, connection-oriented transport service, e.g., mail (SMTP), file transfer (FTP), and virtual terminal service (Telnet); requirements for these application-layer protocols are described in [INTRO:1].
Который можно было бы перевести как (опять спасибо John-1123 и Drop-bear):
Transmission Control Protocol TCP [TCP: 1] является основным виртуальным протоколом транспортной схемы для сети Интернет. TCP обеспечивает надежную, последовательную полнодуплексную доставку потока октетов (8-битный байт). TCP используется приложениями, нуждающимися в надежных способах доставки, ориентированных на соединения между клиентами, например, электронной почтой (SMTP), при передаче файлов (FTP), службы виртуального терминала (Telnet); требования к этим протоколам прикладного уровня описаны в [INTRO:1].Снова никаких гарантий.
Можно предположить зачем же переводчик добавил эти мнимые гарантии. Возможно, он хотел подчеркнуть отличие TCP от UDP (а как следствие и от IP), а может решил обобщить слова "надежность", "контроль" и другие хорошие (и надежные) слова в хорошее (и надежное) слово "гарантии".
"И что из этого?" - спросите вы.
То, что фразу "TCP обеспечивает гарантированную доставку" теперь знает каждый, не задумываясь о природе протоколов, воспринимая якобы гарантированную доставку за аксиому.
А из этого следует:
Этап третий: практический.
Если предыдущий этап не убедил вас в том, что TCP все-таки не гарантирует доставки, то давайте проведем эксперимент:
Откройте любое приложение использующее TCP и начните обмен данными (скачивание музыки, получение почты подойдет). TCP гарантирует доставку? Похоже, что да? А теперь вытащите кабель подключения к сети, выключите модем и отключите WiFi (или что у вас там?) Ну, как? Гарантии TCP все еще в силе? =)
Вот в этом-то и проблема. На самом деле при отправке данных нет никаких гарантий, что они будут доставлены и поэтому хороший программист обязательно предусматривает вариант, когда данные НЕ будут доставлены.
Т.е. просто написать TCPSocket.Send(*data); и ожидать, что все будет хорошо, строить дальнейший код исходя из посылки о том, что есть "гарантия доставки" в корне не верно.
Представляете, если бы для осуществления ремонта линии электропередач вы бы послали команду "отключить подачу ста тысяч вольт" по TCP и думая о гарантированной доставке сразу полезли бы на столб? Есть среди оставшихся хоть один, кто бы рискнул?
Друзья, читайте RFC в оригинале. Это действительно хороший совет.
(Да, перестаньте плеваться те, кто УЖЕ читают RFC в оригинале, я и сам знаю, что оно сложно переваривается и не менее сложно усваивается. Тем не менее это RFC)
Эпилог: правильные гарантии.
Что же на самом деле гарантирует протокол TCP? Об этом очень хорошо сказано в статье википедии о TCP/IP:
TCP — «гарантированный» транспортный механизм с предварительным установлением соединения, предоставляющий приложению надёжный поток данных, дающий уверенность в безошибочности получаемых данных, перезапрашивающий данные в случае потери и устраняющий дублирование данных. TCP позволяет регулировать нагрузку на сеть, а также уменьшать время ожидания данных при передаче на большие расстояния. Более того, TCP гарантирует, что полученные данные были отправлены точно в такой же последовательности. В этом его главное отличие от UDP.Слово "гарантированный" (вначале) забрано в кавычки и все остальное определение на редкость точно и лаконично.
И особенно вкусен конец абзаца, не удержусь и повторю его еще раз:
Более того, TCP гарантирует, что полученные данные были отправлены точно в такой же последовательности. В этом его главное отличие от UDP.
Вот это - правильные гарантии.
Спасибо.
Спасибо всем, кто дочитал до конца. Возможно для опытных программистов моя заметка не была слишком уж полезна, поскольку так или иначе с практикой становится интуитивно понятно, что "любое чертово сетевое соединение нужно так или иначе непрерывно контролировать", а новичкам все это покажется бесполезным философствованием. Но я надеюсь, что все мы будем делать действительно хороший код и с каждым днем все лучше. Возможно не без помощи этого поста.
Всем счастливо, а умному студенту привет и удачно делать свои снежинки.