Протоколы TCP и UDP: в чем разница
Говоря о безопасности информации, мы имеем в виду конфиденциальность, целостность и доступность информации в каждый момент времени. И если с конфиденциальностью и доступностью все понятно, то как обеспечить целостность информации при ее передаче по сети? Для решения этой задачи нам пригодится знание сетевых протоколов. В данной статье мы рассмотрим протоколы TCP и UDP: что из себя представляет каждый из этих протоколов, в чем их отличие и когда целесообразнее использовать UDP подключение, а когда TCP.Они входят в стек протоколов TCP/IP, относятся к транспортному уровню модели OSI и используются для передачи информации от узла к узлу.
UDP
UDP protocol – протокол, обеспечивающий передачу данных (датаграмм) без предварительного создания соединения между хостами. При отправке датаграмм нет уверенности в существовании получателя и его готовности к обмену. Сетевой протокол UDP не обеспечивает также упорядочивание датаграмм при получении. Он используется приложениями для которых существенное значение имеет время доставки, когда нет возможности ждать задержавшиеся или запрашивать потерянные пакеты, например, в системах реального времени. Датаграммы могут доставляться не в заданном порядке, дублироваться или вовсе не доставляться. Поэтому протокол UDP называют «ненадёжным протоколом датаграмм». Приложения, использующие протокол UDP не чувствительны к потерям данных, нарушению порядка получения датаграмм и дублированию. При этом они могут использовать механизмы обеспечения надёжности на прикладном уровне.
TCP
Протокол передачи данных TCP – протокол обеспечивающий надежную доставку пакетов данных, он обеспечивает установку соединения между двумя хостами методом «рукопожатия», после которого может осуществляться обмен данными. Перед началом передачи пакетов через TCP соединение устанавливается сессия с получателем, в рамках которой затем производится передача данных. Это позволяет убедиться в том, что получатель существует и готов принимать данные. После завершения передачи сессия закрывается, получатель извещается о том, что данных больше не будет, а отправитель извещается о том, что получатель извещён. Каждый пакет при обмене имеет свой порядковый номер. TCP автоматически упорядочивает пакеты, используя порядковый номер, и передает после склейки на уровень приложений. После отправки нескольких пакетов, ожидается подтверждение и порядковый номер следующего пакета. Если подтверждение не получено, отправка повторяется, если попытки не увенчались успехом, сессия разрывается. Количество пакетов данных, на которые будет запрашиваться подтверждение, зависит от надежности сети. Если данные теряются, то подтверждение автоматически запрашивается чаще. Это называется механизмом скользящего окна (sliding window), благодаря которому TCP может работать с сетями, независимо от уровня их надежности. Применение TCP целесообразно там, где недопустима потеря данных, например, при авторизации, а также при передаче шифрованной информации.
TCP и UDP отличия
Означает ли это, что протокол UDP не стоит использовать? Вовсе нет. За счет отсутствия «гарантии доставки» протокол UDP обеспечивает более высокую скорость передачи данных, чем TCP. По этой причине UDP оптимален для сетевых и онлайн игр, просмотра потокового видео, организации видео-связи и IP телефонии.
Как сделать выбор: TCP или UDP для vpn?
Программа Whoer VPN по умолчанию использует TCP-протокол, но при необходимости вы можете сменить его на UDP в Настройках одним кликом. Наши клиенты часто спрашивают, какой протокол лучше: tcp или udp для vpn. Прочитав этой статье о tcp и udp протоколах, вы сами можете решить, какой из них лучше подходит именно вам. OpenVPN приложения работают как с UDP, так и с TCP, и оба протокола безопасны и обеспечивают анонимность. Какой из них использовать, зависит от того, для чего вы используете VPN. В дополнение к собственному впн-клиенту, мы предоставляем нашим пользователям Openvpn конфиги для использования с любым подходящим клиентом на выбранной платформе. Рекомендуем вам посмотреть видео-инструкцию Меняем TCP на UDP в OpenVPN на нашем youtube-канале, если вы используете OpenVPN клиент. Подписывайтесь на нас в соцсетях, задавайте вопросы и делитесь полезной информацией с друзьями и близкими!
Чем отличается протокол TCP от UDP, простым языком
Всем привет сегодня расскажу чем отличается протокол TCP от UDP. Протоколы транспортного уровня, следующие в иерархии за IP, используются для передачи данных между прикладными процессами, реализующимися в сетевых узлах. Пакет данных, поступивший от одного компьютера другому через Интернет, должен быть передан процессу-обработчику, и именно по конкретному назначению. Транспортный уровень принимает на себя ответственность за это. На этом уровне два основных протокола – TCP и UDP.
Что означают TCP и UDP
TCP – транспортный протокол передачи данных в сетях TCP/IP, предварительно устанавливающий соединение с сетью.
UDP – транспортный протокол, передающий сообщения-датаграммы без необходимости установки соединения в IP-сети.
Напоминаю, что оба протокола работают на транспортном уровне модели OSI или TCP/IP, и понимание того чем они отличаются очень важно.
Разница между протоколами TCP и UDP
Разница между протоколами TCP и UDP – в так называемой “гарантии доставки”. TCP требует отклика от клиента, которому доставлен пакет данных, подтверждения доставки, и для этого ему необходимо установленное заранее соединение. Также протокол TCP считается надежным, тогда как UDP получил даже именование “протокол ненадежных датаграмм. TCP исключает потери данных, дублирование и перемешивание пакетов, задержки. UDP все это допускает, и соединение для работы ему не требуется. Процессы, которым данные передаются по UDP, должны обходиться полученным, даже и с потерями. TCP контролирует загруженность соединения, UDP не контролирует ничего, кроме целостности полученных датаграмм.
С другой стороны, благодаря такой не избирательности и бесконтрольности, UDP доставляет пакеты данных (датаграммы) гораздо быстрее, потому для приложений, которые рассчитаны на широкую пропускную способность и быстрый обмен, UDP можно считать оптимальным протоколом. К таковым относятся сетевые и браузерные игры, а также программы просмотра потокового видео и приложения для видеосвязи (или голосовой): от потери пакета, полной или частичной, ничего не меняется, повторять запрос не обязательно, зато загрузка происходит намного быстрее. Протокол TCP, как более надежный, с успехом применяется даже в почтовых программах, позволяя контролировать не только трафик, но и длину сообщения и скорость обмена трафиком.
Tcp Udp отличия
Давайте рассмотрим основные отличия tcp от udp.
- TCP гарантирует доставку пакетов данных в неизменных виде, последовательности и без потерь, UDP ничего не гарантирует.
- TCP нумерует пакеты при передаче, а UDP нет
- TCP работает в дуплексном режиме, в одном пакете можно отправлять информацию и подтверждать получение предыдущего пакета.
- TCP требует заранее установленного соединения, UDP соединения не требует, у него это просто поток данных.
- UDP обеспечивает более высокую скорость передачи данных.
- TCP надежнее и осуществляет контроль над процессом обмена данными.
- UDP предпочтительнее для программ, воспроизводящих потоковое видео, видеофонии и телефонии, сетевых игр.
- UPD не содержит функций восстановления данных
Примерами UDP приложений, например можно привести, передачу DNS зон, в Active Directory, там не требуется надежность. Очень часто такие вопросы любят спрашивать на собеседованиях, так, что очень важно знать tcp и udp отличия.
Заголовки TCP и UDP
Давайте рассмотрим как выглядят заголовки двух транспортных протоколов, так как и тут отличия кардинальные.
Заголовок UDP
- 16 битный порт источника > Указание порта источника для UDP необязательно. Если это поле используется, получатель может отправить ответ этому порту.
- 16 битный порт назначения > Номер порта назначения
- 16 битная длина UDP > Длина сообщения, включая заголовок и данные.
- 16 битная контрольная сумма > Контрольная сумма заголовка и данных для проверки
Заголовок TCP
- 16 битный порт источника > Номер порта источника
- 16 битный порт назначения > Номер порта назначения
- 32 битный последовательный номер > Последовательный номер генерируется источником и используется назначением, чтобы переупорядочить пакеты для создания исходного сообщения и отправить подтверждение источнику.
- 32 битный номер подтверждения > Если установлен бит АСК поля «Управление», в данном поле содержит следующий ожидаемый последовательный номер.
- 4 бита длина заголовка > Информация о начале пакета данных.
- резерв > Резервируются для будущего использования.
- 16 битная контрольная сумма > Контрольная сумма заголовка и данных; по ней определяется, был ли искажен пакет.
- 16 битный указатель срочности > В этом поле целевое устройство получает информацию о срочности данных.
- Параметры > Необязательные значения, которые указываются при необходимости.
В UDP протоколе размер окна не используется. Размер окна относится к TCP протоколу, где он определяет количество байтов данных, которые можно отправить без подтверждения получения. Размер окна позволяет экономить трафик, рассмотрим когда его значение равно 1, тут на каждый отправленный ответ, отправитель ждет подтверждения, не совсем рационально.
При размере окна 3, отправитель отправляет уже по 3 кадра, и ждет 4, который подразумевает, что все три кадра у него есть, +1.
Надеюсь у вас теперь есть представления об отличиях tcp udp протоколов.
Популярные Похожие записи:
Как ускорить Google и YouTube в России
- Словарь системного администратора
Работа с функциями даты и времени в PostgreSQL
- Центр обработки данных, основные понятия
- Сравнение маршрутизаторов Cisco и Juniper, что лучше в 2022 году?
- Отличия Global Hot Spare и Dedicated Hot Spare
Сен 20, 2023 03:17 Автор — Сёмин Иван
17 Responses to Чем отличается протокол TCP от UDP, простым языком
Неплохая статья. Затронута важная тема, т. к. даже выбор протокола передачи данных в популярной программе uTorrent версии выше 2.0 требует пояснений. Различные сетевые игры используют указанные протоколы. Т. е. тема актуальная и нужно просвещать людей. Некоторые замечания:
1) к сожалению, не указаны источники;
2) оформление сайта «игрушечное», нет нейтральности.
Учитывая это, я не могу безоговорочно рекомендовать эту статью студентам. Но в целом впечатление от статьи хорошее. Спасибо!
Иван Семин :
Добрый день, источники, это опыт, а на счет оформления, тут у всех свое видение. Но тоже думаю, над улучшением. Спасибо за отзыв.
Позвольте мне написать отзыв об оформлении сайта. Взглянул на статью и сайт ещё раз. Теперь я понял, что это за игрушки: это пингвинята, их много и они разные, это как сборки Линукса. А игрушки они потому, что некоторые изучают компьютеры, «ломая» или изменяя компьютерные игры.
Но это я написал про игрушки над менюшкой. Однако по бокам страницы ещё две игрушки, они немного отвлекают от серьёзной статьи своим туповатым взглядом. При первом посещении сайта не очень приятно смотреть на них, извините. Есть ещё пингвинёнок-шарик, точнее эллипсоид, на каждой авторской картинке. У него глазки-бусинки и это не особо отвлекает, это даже забавляет. Ещё одна мысль возникла. Возможно, игрушки изображены, чтобы не пугать детей и всех людей, плохо разбирающихся в компьютерах. Многие не понимают и боятся всякие компьютерные железки и пр.
Когда я был ребёнком, я изучал программирование по книжке «Бейсик — это просто». _http://coollib.com/b/233279
Там был забавный персонаж-робот, иллюстрирующий работу ЭВМ. С ним чтение книжки было приятным и увлекательным.
Если проводить аналогию, то забавные персонажи-игрушки на этом сайте как бы говорят: «Правильная настройка ПК — это просто». В общем, чувствуется авторский подход к оформлению.
Иван Семин :
Спасибо за отзыв, очень приятно слушать мнение людей, а пингвины сверху, это символы linux, и вместе образуют слово Pyatilistnik.org, задумка такая была))
TCP и UDP, или Два столпа Интернета
В этой серии статей мы пытаемся описать, как работает CDN и какие технологии делают его существование возможным.
В предыдущей статье мы обсудили иерархию Интернета, разницу между средами передачи данных и путь запроса от компьютера пользователя до сервера, расположенного на другом конце земного шара. В этой поднимемся на несколько уровней выше, чтобы разобрать каким «языком» пользуются компьютеры, чтобы общаться друг с другом.
План
Невозможно по-быстрому рассказать обо всём, что касается устройства Интернета. Потому в этой и следующих статьях мы будем рассматривать только определённое подмножество технологий – часть между физическим уровнем и уровнем приложения.
Не будем говорить о том, как компьютеры используют электричество для представления и передачи данных. Это очень интересная тема, но слишком низкоуровневая для этого цикла.
Но и рассказывать про то, как браузер загружает страницы, тоже не будем. HTTP-запросы, сжатие, языки программирования, рендеринг страниц – всё мимо.
Что нам интересно, так это то, как данные находят путь от одного компьютера до другого.
Коммутация
Если вы достаточно стары, то скорее всего застали проводные телефоны, которыми раньше активно пользовалось человечество. А может, у вас даже до сих пор есть такой! В таком случае, скорее всего вы знаете, что вот ещё лет сто назад они работали в полуавтоматическом режиме.
Сперва вам нужно было поднять трубку и сказать телефонисту (который был реальным человеком), что вы хотите, чтобы вас соединили с вашим знакомым из другого города. Телефонист выслушал бы ваш запрос, повесил бы трубку, а позже перезвонил бы уже с вашим другом «на линии» (on line – пер.).
Чего вы возможно можете не знать, так это того, что происходило за кадром. А там телефонист переключал кабели между портами, чтобы соединить вас с вашим другом:
То, что происходит на картинке – это коммутация каналов. Коммутация каналов – это способ соединения двух узлов сети, при котором между ними устанавливается выделенный канал связи. Через этот канал и происходит общение. Иными словами, когда вы звонили другу, кто-то или что-то в буквальном смысле строил путь из кабелей между вами.
Как нетрудно догадаться, подобный тип коммуникаций не очень-то подходит для Интернета, потому что мы постоянно подключаемся к огромному количеству серверов по всему миру. Строить такую высоконагруженную сеть на основе коммутации каналов было бы слишком безумно. Да и было бы слишком дорого создавать такую сеть, не говоря уже о её поддержке.
Вместо этого Интернет построен на основе коммутации пакетов. При таком способе построения сети, для создания соединения между двумя узлами не требуется физического переключения кабелей. Когда мы посылаем сообщение от одного компьютера к другому, это сообщение проходит через различные сети, каждая из которых сама решает, куда лучше его отправить.
С какой-то точки зрения это может звучать безумно, но по сути в Интернете нет какого-то главного «координатора», который бы решал, по какому пути каждый пакет должен идти. Наш компьютер просто «бросает» пакет в сеть, и все устройства, через которые он проходит, пытаются решить, какой путь для этого пакета будет наиболее оптимальным. Удивительно, но в большинстве случаев, у этих устройств получается достигнуть поставленной цели. Всё благодаря протоколам!
Протоколы
Протокол – это набор правил, определяющий, как узлы сети должны передавать данные друг другу. Вы скорее всего слышали про высокоуровневые протоколы – HTTP, SSH, IMAP, DHCP.
В сфере телекоммуникаций огромное количество протоколов, каждый из которых решает какую-то свою задачу. Из-за того, что их много, есть даже специальные модели, определяющие «уровни протоколов». Если представить, что ваше сообщение, – это конфета, то протоколы в каком-то плане играют роль обёрток для этой конфеты.
Предположим, что вы заказали в подарок своему другу большую плитку вкусного шоколада от местной шоколадной фабрики.
Первым делом плитку шоколада запакуют в обёртку. Затем всё это положат в брендированный пакет. После этого, кто-нибудь в отделе доставки увидит, что это шоколадка – подарок, а потому пакет дополнительно украсят, дабы всё выглядело подобающе. Наконец, фабрика передаст пакет с подарком почтовой компании.
Почтовая компания же, получив пакет, запакует его в коробку и напишет на ней адрес вашего друга. Наконец, они погрузят всё это в грузовик и отправят в точку выдачи.
Когда грузовик приедет в точку выдачи, процесс пойдёт в обратную сторону: сперва выгрузят, потом проверят адрес получателя, распакуют коробку и так далее.
Весь этот процесс оборачивания-разворачивания шоколадки – ровно то, как работают протоколы в Интернете:
История OSI и TCP/IP
Так сложилось, что есть две модели, описывающие уровни протоколов. Одна из них теоретическая – модель OSI, а другая практическая – TCP/IP.
В 70-80-х годах прошлого столетия в сфере телекоммуникаций было много проблем, но и много возможностей. Тогда ещё не было такого Интернета, каким мы его знаем сегодня. Была лишь куча сетей, созданных разными компаниями. И этим сетям нужен был какой-то общий «язык» для общения, или скорее стандарт. А потому многие инженеры работали над тем, чтобы этот самый стандарт создать. Если говорить грубо, то для нас важно то, что в конечном итоге эти люди разделились на две группы.
Первая верила, что подобный стандарт должен создаваться открыто, со всеобщим обсуждением, с решением всех возникающих проблем и вопросов. Чтобы всем было удобно. Эта группа назвала стандарт, который она пыталась создать, – OSI, или Open Systems Interconnection.
Другая группа пошла иным путём, и начала разрабатывать и тестировать протоколы на основе тех сетей, что у них уже были. Так они создали TCP – Transmission Control Protocol, и IP – Internet Protocol. Изначально эти два протокола были частью одного большого, но впоследствии были разбиты на два для упрощения работы с ними.
Эта группа успешно протестировала протокол и перевела сети, которые были под её руководством, на него. Это случилось первого января 1983-го года. Так что, можно сказать, что это день, когда родился Интернет.
После этого TCP/IP начал набирать популярность, потому что он «просто работал». Плюс, эта модель была бесплатной, в то время как авторы OSI хотели взимать деньги со всех, кто пользовался бы их стандартами.
И что в итоге стало с OSI? Инициатива провалилась. Из-за идеи «открытости» те, кто принимал тогда решения, потратили очень много времени на обсуждения и споры. Часть из них лоббировали идеи, которые были выгодны большим корпорациям. Из-за других же дискуссии постоянно увязали в обсуждении незначительных деталей.
Однако, несмотря на то, что OSI как сетевая модель не нашла своего применения в реальном мире, она всё ещё остаётся хорошей теоретической моделью, описывающей уровни протоколов. Но модель, которая была имплементирована и захватила мир – TCP/IP.
Вот, как выглядят уровни протоколов в этих моделях:
TCP/IP
Обычно, когда обсуждают OSI и TCP/IP, пытаются сравнить эти модели и найти соответствия между их уровнями. Хоть картинка выше и выглядит как сравнение, мы не будем этого делать, потому что то, как соотносятся их уровни, не особо важно для нашей статьи. Да и «многоуровневость» как таковая «может быть вредной», если верить RFC 3439.
Ключевые протоколы модели TCP/IP, очевидно, TCP и IP. Всё остальное в этой модели описано довольно туманно, и даже авторы учебников и справочников по сетям не могут сойтись на чётких названиях и количестве уровней в этой модели.
Есть ли физический уровень под уровнем сетевого доступа? Нужно ли вообще называть уровень сетевого доступа так, или это всё же «канальный уровень»? Вокруг TCP/IP много таких вопросов. Однако, всё это не так важно, потому что основная суть стека очень простая.
Предположим, есть два приложения в сети, которые хотят обменяться данными. Пусть один из них сгенерирует сообщение. Не важно, какое именно. Это может быть HTTP-запрос, а может и нет. Это сообщение генерируется на уровне приложения.
Дальше оно передаётся на транспортный уровень, где к нему добавляется TCP или UDP-заголовок. Этот заголовок содержит информацию о портах, которые используются приложениями, и некоторую другую информацию (но о ней чуть позже). В результате получается то, что обычно называется датаграммой или сегментом.
Затем, сегмент передаётся на межсетевой уровень. Там к нему добавляется IP-заголовок, содержащий адреса компьютеров, на которых запущены приложения, участвующие в этом обмене данными. Результат объединения сегмента и IP-заголовка обычно называется пакетом.
Справедливости ради, нет чёткой разницы между датаграммами, сегментами и пакетами. В большинстве случаев для простоты они все называются «пакетами». Термины «датаграмма» и «сегмент» используются, только когда нужно явно указать тип протокола, с которым мы имеем дело.
Наконец, пакет передаётся на канальный уровень, где кодируется и уходит по проводам в сторону точки назначения. Протоколы на этом уровне так же добавляют свой заголовок в каждый пакет, и в результате получается кадр (или «фрейм» – пер.).
Кадры обычно содержат не только заголовок, но и окончание. Например, Ethernet-кадр для нашего сообщения может выглядеть примерно так:
Когда кадр передаётся от одного промежуточного узла сети к другому, эти узлы разбирают кадр на части, проверяют IP-заголовок пакета, определяют что с ним делать, а затем создают новый кадр для этого пакета и передают его следующему узлу.
Иными словами, когда путь сообщения выглядит как-то так:
То работа протоколов на пути этого сообщения выглядит так:
Окей, теперь мы знаем, что модель TCP/IP определяет протоколы транспортного и межсетевого уровней, но не особо тщательно описывает протоколы прикладного и канального уровней. Давайте теперь посмотрим на транспортный уровень чуть поближе.
TCP и UDP
Транспортный уровень модели TCP/IP основан на двух китах: Transmission Control Protocol и User Datagram Protocol. Есть и другие протоколы на этом уровне (например, QUICK), но они не так часто используются.
Протоколы транспортного уровня используются для адресации пакетов с порта приложения отправителя на порт приложения получателя. Более того, протоколы этого уровня не знают ничего про различия в узлах сетей. Всё, что им требуется знать про адресацию, это то, что есть приложение, отсылающее сообщение, и оно для отправки использует какой-то порт. И приложение, которое получает сообщение, тоже использует какой-то порт. Основная «адресация внутри Интернета» же реализована на межсетевом уровне, и будет описана в следующей статье.
UDP куда «легче» и проще, чем TCP, но в то же время UDP не такой надёжный, как TCP. Чтобы посмотреть на разницу между ними поподробнее, давайте начнём с User Datagram Protocol.
User Datagram Protocol
Этот протокол используется для «связи без установки соединения» (connectionless communication – пер.). Один узел сети просто отсылает пакеты, адресуя их другому узлу. Отправитель не знает ничего о том, готов ли получатель к приёму пакетов, и вообще, существует ли этот получатель. Отправитель также не ждёт какого-либо подтверждения о том, что получатель принял предыдущие пакеты.
Пакеты, передаваемые с помощью UDP, иногда называются датаграммами. Этот термин обычно используется тогда, когда важно подчеркнуть, что пакет передаётся без установки соединения.
Заголовок UDP-пакета состоит из 8 байт, которые включают в себя:
- порт отправителя;
- порт получателя;
- длину датаграммы;
- контрольную сумму.
Вот так просто. Типичная UDP-датаграмма выглядит так:
Пробуем
UDP-сервер очень просто поднять самому. Вот, например, такой сервер, написанный на Node.js ровно так, как об этом сказано в официальной документации:
const dgram = require('dgram'); const server = dgram.createSocket('udp4'); server.on('error', (err) => < console.log(`error:\n$`); server.close(); >); server.on('message', (msg, rinfo) => < console.log(`got a message from $:$: $`); >); server.on('listening', () => < const address = server.address(); console.log(`listening $:$`); >); server.bind(8082);
Давайте ж запустим его:
$ node udp.js server listening 0.0.0.0:8082
Теперь мы можем использовать netcat для отправки датаграмм из соседнего окна терминала:
$ nc -u 127.0.0.1 8082 Hello, server! Do you have a minute to talk about UDP?
Наш сервер успешно логирует отправленные нами датаграммы после их получения:
$ node udp.js server listening 0.0.0.0:8082 server got a message from 127.0.0.1:55823: Hello, server! server got a message from 127.0.0.1:55823: Do you have a minute to talk about UDP?
Как видите из логов выше, netcat решил использовать порт 55823 для отправки пакетов. Если мы возьмём Wireshark и перехватим эти пакеты, то увидим следующее:
Если не хотите поднимать Node.js-сервер и перехватывать трафик самостоятельно, но хочется потыкать в Wireshark, качайте дамп-файл.
Итак, что у нас тут? Порт отправителя – 55823, тот, что выбрал netcat. Порт получателя – 8082, тот, что указан у нас в настройках сервера. Длина пакета 48 байт, потому что 8 из них – это заголовок, а ещё 40 – наше сообщение. И в конце контрольная сумма, указанная netcat.
Как видите, в логе Wireshark нет никаких ответов от сервера, а потому клиент не может быть уверен, что сервер действительно получил его датаграммы. По этой причине UDP используется там, где не страшно потерять часть сообщений. Например, при видео- или аудио-стриминге. Да, можно использовать для этого и TCP, но, как вы увидите чуть через минуту, использование TCP замедлило бы в таком случае передачу данных.
Справедливости ради, хоть UDP и не предполагает наличия подтверждений о получении сообщений, мы всё ещё можем узнать о том, что получатель недоступен. С помощью ICMP. Попробуйте отправить сообщения используя netcat, не включив перед этим UDP-сервер, и посмотрите, что будет в логах Wireshark. Вот, что вы там увидите; а вот дамп-файл.
Transmission Control Protocol
Если UDP простой и не требующий установки соединения, то TCP – сложный и требующий. Перед тем, как начать передачу данных, клиент и сервер должны подключиться друг к другу и договориться о том, как они будут осуществлять эту самую передачу.
В отличие от датаграмм в UDP, пакеты, создаваемые TCP, называются сегментами.
А вот, некоторые из тех задач, что решает TCP во время передачи данных:
- Убеждается в том, что сегменты доставлены в нужном порядке.
- Убеждается в том, что они вообще доставлены.
- Контролирует поток пакетов, чтобы не перегружать им узлы сети.
Работы много, а потому и заголовок у TCP как минимум 20 байт, а то и больше. Он включает в себя:
- порт отправителя;
- порт получателя;
- порядковый номер;
- номер подтверждения;
- длину заголовка;
- флаги;
- размер окна;
- контрольную сумму;
- указатель важности;
- дополнительные опции.
Схема пакета выглядит так:
Порт отправителя, порт получателя и контрольная сумма – такие же поля, как и в UDP. А чтобы объяснить оставшиеся, давайте перейдём к тестам.
Пробуем
Поднимем простой TCP-сервер с помощью Node.js (опять же, используя код из официальной документации).
const net = require('net'); const server = net.createServer(connection => < console.log('client connected'); connection.on('end', () =>< console.log('client disconnected'); >); connection.write('Hello, client!\n'); // 'connection' – это поток, который мы можем перенаправить // сперва перенаправляем его в stdout, чтобы логировать сообщения от клиента connection.pipe(process.stdout); // затем перенаправляем в самого себя, // тем самым отправляя в ответ то, сообщение, что получили connection.pipe(connection); >); server.on('error', (err) => < console.log(`server error:\n$`); server.close(); >); server.listen(8082, () => < const address = server.address(); console.log(`server listening $:$`); >);
Этот код похож на тот, что мы использовали для UDP-сервера, но вместо простой работы со входящими сообщениями как со строками, мы теперь оперируем объектом соединения. Этот объект позволяет нам не только выводить сообщения, когда мы их получаем, но и отправлять что-нибудь в ответ, и определять подключение-отключение клиента. Если вы когда-либо поднимали самостоятельно HTTP-сервера, то многое тут будет вам знакомо.
$ node tcp.js server listening . 8082
Два двоеточия вместо привычного IP означают, что сервер забиндился на localhost с помощью IPv6, но это не принципиально сейчас
Теперь используем netcat в соседнем окне терминала, чтобы соединиться с нашим сервером по TCP:
$ nc 127.0.0.1 8082 Hello, client!
Строка, что вы видите в логе, пришла к нам с сервера как только соединение было установлено. Вот, как выглядят логи сервера:
$ node tcp.js server listening . 8082 client connected
Как видите, сервер получил уведомление от клиента и знает, что этот клиент существует, и что он собирается что-то прислать. Давайте пошлём, раз так:
$ nc 127.0.0.1 8082 Hello, client! # сообщение от сервера Hello, server! # наше сообщение Hello, server! # ответ от сервера Hey, stop it! # наше сообщение Hey, stop it! # ответ от сервера
Мы написали простейший эхо-сервер, который присылает нам в ответ всё то, что получает от нас.
Закроем netcat нажатием Ctrl+C и посмотрим на логи сервера:
$ node tcp.js server listening . 8082 client connected Hello, server! Hey, stop it! client disconnected
Там появились два сообщения, что мы присылали, и уведомление о том, что клиент отключился.
Окей, и как же это возможно, что сервер знает о том, что появилось какое-то «соединение», если мы ещё не послали никаких данных? Чтобы разобраться, обратимся снова к Wireshark.
Вот, как наш обмен сообщениями выглядел там:
И снова, если не хочется поднимать сервер самостоятельно, но хочется потыкать в логи, держите дамп.
Как много всего! Давайте посмотрим на это в деталях.
Рукопожатие
Прежде, чем клиент начнёт посылать данные серверу, они оба, как мы уже говорили, должны установить соединение. Эта «установка» обычно называется рукопожатием.
В нашем случае рукопожатие происходит в три этапа:
- Клиент посылает серверу пакет, который называется SYN.
- Сервер отвечает пакетом SYN-ACK.
- Клиент отвечает серверу пакетом ACK.
Названия пакетов взяты из названий флагов, которые установлены в TCP-заголовках этих пакетов. Вот как первый из пакетов рукопожатия выглядит в Wireshark:
Как видите, один из битовых флагов установлен в 1. Флаг называется «Syn», что есть сокращение от «Синхронизация».
TCP – надёжный протокол, что означает, что отправитель всегда в курсе, дошёл ли пакет до получателя или нет. Чтобы сделать такое уведомление возможным, TCP использует специальные типы пакетов (SYN, ACK и пр.), а также каждый TCP-заголовок содержит два числа: порядковый номер и номер подтверждения.
Порядковый номер (Sequence number – пер.) показывает, сколько данных отправитель уже послал в сторону получателя. Этот номер увеличивается на 1 каждый раз, когда отправитель посылает пакеты с флагами SYN или FIN, а также увеличивается на размер полезных данных, если они были переданы. Число, указанное в номере, не учитывает текущий пакет. А потому порядковый номер первого пакета, посылаемого клиентом, всегда равен 0.
Номер подтверждения (Acknowledgement number – пер.) же показывает сколько данных отправитель этого пакета получил на текущий момент. Это число как бы отзеркаливает порядковый номер «собеседника», но опережает его на один шаг. А потому первый пакет, отправленный сервером, имеет номер подтверждения равный 1.
Вообще, начальные значения для этих номеров выбираются случайным образом. Но для простоты обычно оперируют их относительными значениями, как, например, вы можете видеть на скриншоте Wireshark выше.
Эти числа важны, потому что позволяют обеим сторонам понимать статус передачи данных. И клиент, и сервер, оба ожидают получить определённые значения порядкового номера и номера подтверждения от противоположной стороны. А если вдруг действительно полученные значения расходятся с ожидаемыми, значит где-то произошла ошибка, и возможно кто-то из них должен переотправить какие-то пакеты.
Так вот. Как выглядит рукопожатие в нашем случае:
И когда рукопожатие закончено, наш сервер как раз и понимает, что клиент готов передавать данные, и начинает их от него ожидать.
Передача данных
Когда рукопожатие закончено, начинается передача данных.
Как видно в логе выше, каждый кусок данных отправленный одной стороной, подтверждён (ACK-ed – пер.) отдельным сегментом, отправленным другой стороной.
Выглядит легко и просто, но это так лишь потому, что наш пример совсем уж учебный. В реальном же мире полно проблем: пакеты могут потеряться, канал может быть забит, может возникнуть какая-нибудь ошибка, и так далее. TCP обрабатывает все эти ситуации. Как? Это история для отдельной серии статей. Дайте нам знать, если вам интересно было бы про это почитать.
А, кстати. У каждого пакета в логе выше выставлен флаг PSH. Это необычно, и в реальной жизни этот флаг не так часто используется. Вероятно, это особенность netcat.
Завершение соединения
Когда один из «собеседников» решает прекратить общение, он инициирует завершение соединения. Этот процесс похож на рукопожатие, но вместо флага SYN используется флаг FIN.
Вот как выглядит завершение соединения в нашем логе:
Как вы можете заметить, для завершения соединения потребовалось четыре сегмента, а не три, как в случае с рукопожатием. Схема выглядит чуть иначе, потому что при завершении соединения, собеседник (в нашем случае сервер) должен сперва уведомить приложение, использующее TCP, о том, что соединение вот-вот завершится. И когда это приложение будет готово к завершению, тогда TCP собеседника отправит свой FIN-пакет.
И поскольку участники обмена пакетами должны подобным образом «договориться» о завершении, мы можем подписаться на соответствующее событие у себя в приложении. Что мы выше в коде и сделали.
Кстати, иногда завершение соединения вызывается не сегментом с флагом FIN, а сегментом с флагом RST. Это не совсем обычная практика, то такое возможно. Также RST-флаг может быть использован для атаки, которая может прервать существующее соединение между TCP-узлами. См. статью Роберта Хитона, если вдруг интересно.
Подытожим
Интернет работает за счёт коммутации пакетов. Основной его стек – TCP/IP. Два главных протокола транспортного уровня этого стека – TCP и UDP, на каждый из которых мы по-быстрому посмотрели в этой статье.
В следующей же посмотрим на то, как устроен Internet Protocol, и разберём, как благодаря ему все компьютеры мира могут общаться друг с другом.
От переводчика: в этой статье было много сетевых терминов – названий уровней, моделей, протоколов. Сложно было понять, в каких местах правильнее переводить, в каких нет. Я руководствовался тем, что протоколы и модели в рунете всё же чаще называют латиницей, не переводя, в то время как уровни всё же переводят. Изображения оставил без перевода. Если вам кажется, что получилась мешанина, и вы что-то не поняли – напишите мне, пожалуйста, где именно возникло недопонимание, я что-нибудь придумаю и обновлю статью.
Следующая статья уже доступна на английском. Переведу её, если эта не потонет в минусах.
- IT-инфраструктура
- Сетевые технологии
Протоколы TCP и UDP
Обмен данными, ориентированный на соединения, может использовать надежную связь, для обеспечения которой протокол уровня 4 посылает подтверждения о получении данных и запрашивает повторную передачу, если данные не получены или искажены. Протокол TCP использует именно такую надежную связь. TCP используется в таких прикладных протоколах, как HTTP, FTP, SMTP и Telnet.
Протокол TCP требует, чтобы перед отправкой сообщения было открыто соединение. Серверное приложение должно выполнить так называемое пассивное открытие (passive open), чтобы создать соединение с известным номером порта, и, вместо того чтобы отправлять вызов в сеть, сервер переходит в ожидание поступления входящих запросов. Клиентское приложение должно выполнить активное открытие (active open), отправив серверному приложению синхронизирующий порядковый номер (SYN), идентифицирующий соединение. Клиентское приложение может использовать динамический номер порта в качестве локального порта.
Сервер должен отправить клиенту подтверждение (ACK) вместе с порядковым номером (SYN) сервера. В свою очередь клиент отвечает АСК, и соединение устанавливается.
После этого может начаться процесс отправки и получения сообщений. При получении сообщения в ответ всегда отправляется сообщение АСК. Если до получения АСК отправителем истекает тайм-аут, сообщение помещается в очередь на повторную передачу.
Поля заголовка TCP перечислены в следующей таблице:
Поле | Длина | Описание |
---|---|---|
Порт источника | 2 байта | Номер порта источника |
Порт назначения | 2 байта | Номер порта назначения |
Последовательный номер | 4 байта | Последовательный номер генерируется источником и используется назначением, чтобы переупорядочить пакеты для создания исходного сообщения и отправить подтверждение источнику. |
Номер подтверждения | 4 байта | Если установлен бит АСК поля «Управление», в данном поле содержится следующий ожидаемый последовательный номер. |
Смещение данных | 4 бита | Информация о начале пакета данных. |
Резерв | 6 битов | Резервируются для будущего использования. |
Управление | 6 битов | Биты управления содержат флаги, указывающие, верны ли поля подтверждения (АСК), указателя срочности (URG), следует ли сбрасывать соединение (RST), послан ли синхронизирующий последовательный номер (SYN) и т. д. |
Размер окна | 2 байта | В этом поле указывается размер приемного буфера. Используя подтверждающие сообщения, получатель может информировать отправителя о максимальном размере данных, которые тот может отправить. |
Контрольная сумма | 2 байта | Контрольная сумма заголовка и данных; по ней определяется, был ли искажен пакет. |
Указатель срочности | 2 байта | В этом поле целевое устройство получает информацию о срочности данных. |
Опции | переменная | Необязательные значения, которые указываются при необходимости. |
Дополнение | переменная | В поле дополнения добавляется столько нулей, чтобы заголовок заканчивался на 32-битной границе. |
TCP — это сложный, требующий больших затрат времени протокол, что объясняется его механизмом установления соединения, но он берет на себя заботу о гарантированной доставке пакетов, избавляя нас от необходимости включать эту функциональную возможность в прикладной протокол.
Протокол TCP имеет встроенную возможность надежной доставки. Если сообщение не отправлено корректно, мы получим сообщение об ошибке. Протокол TCP определен в RFC 793.
UDP — User Datagram Protocol
В отличие от TCP UDP — очень быстрый протокол, поскольку в нем определен самый минимальный механизм, необходимый для передачи данных. Конечно, он имеет некоторые недостатки. Сообщения поступают в любом порядке, и то, которое отправлено первым, может быть получено последним. Доставка сообщений UDP вовсе не гарантируется, сообщение может потеряться, и могут быть получены две копии одного и того же сообщения. Последний случай возникает, если для отправки сообщений в один адрес использовать два разных маршрута.
UDP не требует открывать соединение, и данные могут быть отправлены сразу же, как только они подготовлены. UDP не отправляет подтверждающие сообщения, поэтому данные могут быть получены или потеряны. Если при использовании UDP требуется надежная передача данных, ее следует реализовать в протоколе более высокого уровня.
Так в чем же преимущества UDP, зачем может понадобиться такой ненадежный протокол? Чтобы понять причину использования UDP, нужно различать однонаправленную передачу, широковещательную передачу и групповую рассылку.
Однонаправленное (unicast) сообщение отправляется из одного узла только в один другой узел. Это также называется связью «точка-точка». Протокол TCP поддерживает лишь однонаправленную связь. Если серверу нужно с помощью TCP взаимодействовать с несколькими клиентами, каждый клиент должен установить соединение, поскольку сообщения могут отправляться только одиночным узлам.
Широковещательная передача (broadcast) означает, что сообщение отправляется всем узлам сети. Групповая рассылка (multicast) — это промежуточный механизм: сообщения отправляются выбранным группам узлов.
UDP может использоваться для однонаправленной связи, если требуется быстрая передача, например для доставки мультимедийных данных, но главные преимущества UDP касаются широковещательной передачи и групповой рассылки.
Обычно, когда мы отправляем широковещательные или групповые сообщения, не нужно получать подтверждения из каждого узла, поскольку тогда сервер будет наводнен подтверждениями, а загрузка сети возрастет слишком сильно. Примером широковещательной передачи является служба времени. Сервер времени отправляет широковещательное сообщение, содержащее текущее время, и любой хост, если пожелает, может синхронизировать свое время с временем из широковещательного сообщения.
Заголовок UDP гораздо короче и проще заголовка TCP:
Поле | Длина | Описание |
---|---|---|
Порт источника | 2 байта | Указание порта источника для UDP необязательно. Если это поле используется, получатель может отправить ответ этому порту. |
Порт назначения | 2 байта | Номер порта назначения |
Длина | 2 байта | Длина сообщения, включая заголовок и данные. |
Контрольная сумма | 2 байта | Контрольная сумма заголовка и данных для проверки |
UDP — это быстрый протокол, не гарантирующий доставки. Если требуется поддержание порядка сообщений и надежная доставка, нужно использовать TCP. UDP главным образом предназначен для широковещательной и групповой передачи. Протокол UDP определен в RFC 786.