Транспортный уровень

Рассмотрим теперь четвертый уровень - уровень TCP. Третий уровень дал нам теоретическую возможность доставить пакет до получателя. На четвертом решается вопрос реализации этой возможности:

Иными словами, мы должны решить следующий вопрос: доставлен ли пакет? Ясно, что в описываемой нами структуре это принципиально. Получение подтверждения, что переданные данные получены, очень важно, как для отслеживания качества взаимодействия по сети, так и по другим причинам. Механизм прост: когда абонент получает данные, он отправляет подтверждение. Когда подтверждение получено, можно отправлять следующий фрагмент данных.

Должны мы предусмотреть и следующие возможности:

Возможна такая ситуация: данные были отправлены, но абонент ничего не получил. Пусть передаваемая информация разделена, скажем, на четыре пакета, которые отправляются последовательно, один за другим. Допустим, что абонент получает 1-й, 2-й и 4-й пакеты (3-й потерялся "по пути"). Нужно разработать механизм объединения этих четырех пакетов в поток так, чтобы получатель понял, что он не получил именно 3-й пакет (то есть тот 4-й, который он получил, есть именно 4-й, а не 3-й). В противном случае при "перемешивании" пакетов (например, в результате причуд маршрутизации вначале придет 4-й пакет, а только потом - 3-й) будет невозможно восстановить исходный порядок пакетов, а следовательно и передваваемую информацию. Итак, необходимо решить вопрос манипулирования потоком данных.

Разумеется, начать следует с решения вопроса о подключении. Иными словами, перед тем как данные передавать, следует убедиться в том, что есть кому их принимать. К примеру, мы хотим отправить данные абоненту с адресом 158.250.10.1. Однако "существует" ли он для нас - априори неизвестно. Даже в случае его существования мы не можем гарантировать, что маршрут, по которому пойдет пакет, функционирует корректно. Прежде чем начать передачу данных данному абоненту, следует обменяться с ним вспомогательной информацией. Если абонент не отвечает, то "добраться" до него мы не сможем, так что передавать данные бессмысленно.

Однако всегда ли необходимо решение всех пяти перечисленных задач? Ясно, что если вся информация, которую надо передать, помещается в один пакет (датаграмму), то можно пойти более простым путем. Чтобы была возможность выбора, на уровне TCP поддерживается два протокола: надежный (TCP) и ненадежный (UDP).

Еще про манипуляцию потоков данных. Она нужна вот для чего: когда мы передаем сразу два потока данных, нужно сделать так, чтобы эти потоки друг от друга отличались.

Итак, у нас есть пять задач:

Эти пять задач обыкновенно решаются именно на уровене TCP. Можно считать, что это пять требований к решению вопроса доставки.

Итак, помимо TCP существует еще и UDP. Следует разобраться, когда какой протокол использовать. Разберем подробнее наш пример. Допустим, мы хотим послать ровно один пакет. Зачем нам организация из него потока данных? Зачем отслеживание качества канала? Зачем, в конце концов, подключение? Если вся информация, которую мы собираемся передавать, умещается в один акт передачи данных, то ничего из перечисленного организовывать не нужно. В крайнем случае - переложить на "вышележащий" протокол. Почему так? Дело в том, что проверка контрольной суммы осуществляется и при использовании протокола UDP, поэтому единственная возможная проблема - потеря пакета. Но в случае соединения по протоколу TCP дела обстоят не лучше: если первый пакет в соединении не дошел до абонента, то соединение просто не установится. Следовательно, в нашем случае разумно использовать UDP, а потом просто проверить: дошел ли наш пакет? К примеру, именно так устроен протокол DNS: на UDP-запрос должен прийти ответ, который, с одной стороны, подтверждает корректную доставку и, с другой стороны, несет содержательную информацию.

Именно по этой причине на уровне TCP всего два протокола. Если на уровне IP протоколов гораздо больше (к примеру, протоколы туннелирования, L2TP и прочие), то здесь их в точности два. Один из них пять перечисленных свойств поддерживает - это TCP. Другой же не поддерживает ни одного из них, потому что все заключено в одной посылке данных, - это UDP.

TCP

Я не знаю, нужно ли в рамках этого курса рассказывать, как устроено трехуровневое подключение по TCP, поэтому я расскажу довольно коротко про это. Все начинается с установления подключения, т.е. инициатор подключается.. условно говоря, клиент подключается к серверу, и прежде чем вот это подключение не произойдет, ничего другого не может начаться. При этом надо знать, что подключение по TCP двустороннее, т.е. данные передаются в обе стороны. Клиентом мы называем программу, которая хочет, сервером -- которая может. Клиент -- это тот, кто инициирует подключение, а сервер, этот кто на него отвечает. TCP -- это двустороннее подключение. Данные передаются как от клиента к серверу, так и от сервера к клиенту.

Второе. TCP устроен по принципу подтверждение, каждый TCP-пакет, который может быть гораздо больше, чем IP пакет, после того как он принят сервером, на него генерируется подтверждение, дескать, все принято, все хорошо, или, если он побился по дороге или пришло что-то из того же потока данных но не соответствующее ожиданиям, то вместо подтверждения приходит ошибка, или же, если в какой-то момент произошёл таймаут, и очередного пакета внутри потока данных не пришло, то также приходит вместо подтверждения ошибка, ты что мне шлёшь 12-й, я хочу 3-й. Это процесс симметричный, клиент с сервером играют в волейбол, когда ты посылаешь пакет серверу, он тебе посылает ответ, то бишь подтверждение, и в нём какие-то свои данные, хотя может и голове подтверждение придти, но их можно объединять. Данные, связанные с управлением и собственно данные можно объединять. (Коробка из двух частей, каждый раз передаётся что-нибудь в одну сторону, а заодно и подтверждение чего-то, переданного в прошлый раз в обратную сторону.)

Все TCP-пакеты пронумерованы, есть понятие seqn (sequence number), и в каждом TCP-соединении их два, в каждую сторону передачи, это произвольно взятые числа, которые каждый раз увеличиваются на объём переданных данных. Это одновременно позволяет вычислять последовательность пакетов и позволяет выяснять, что пропало и не сдублировался ли пакет, такое волшебное число. Везде считается контрольные суммы, что касается отслеживания. сост канала, то тут довольно хитрая технология, в описание вдаваться не буду, суть такая: поначалу обмен идёт маленькими пакетами, и чем успешнее идет обмен, чем больше данных готова принять принимающая сторона, тем больше данных готов отправить отправитель.

(tcpdump host esyr.org) (Esc+_ --- вставить последний аргумент предыдущей команды в место курсора) а теперь второе окошечко, и скажем telnet. Вот тут Esc+_ работать не будет... вовсю тут фигачат... вот оно здесь началось, вот мы со своего адреса пошли на msk-f41.host-telecom на 22, вот наш sequence number с окном нулевой длины, вот они пришёл с нулевым окном обратно, и вот он пошел дальше увеличиваться, тык-тык-тык.

Для того, чтобы выполнить задачу разделения данных, к паре (адрес отправителя, адрес получателя) появляется ещё одно понятие --- порт. Оно участвует в TCP, и оно же еще немножко помогает на уровне интерпретации данных.

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

Мы сначала подключились по этому (89.188.104.91) ip-шнику на 80-й порт, а потом подключились по этому (89.188.104.91) ip-шнику на 22 порт, и в случае 22 нас ожидал какой-то сервер, какой-то OpenSSH, какой-то Debian, понимаете ли...

Кстати, вы ключи обновили? --- М? --- Ключи обновили? --- Да, конечно. --- (Черт!)

Поскольку установление подключения двустороннее, то когда происходит ответное установление подключения от сервера к клиенту, оно происходит также по определенному порту, который клиент ему просто сообщает, здесь порт получателя это ssh (22), а у клиента это 44670, и он тут везде сохраняется, как и порт ssh. Если вы устанавливаете следующее подключение к тому же хотя бы, серверу, в качестве порта отправителя используется произвольное другое число, именно поэтому вы можете различить эти два потока данных, даже если адрес получателя, порт получателя и ip отправителя у них одинаковый, а вот порт отправителя у них разный, потому что каждое TCP-соединение использует свой собственный порт для идентификации отправителя.

Так что эта четверка (адрес и порт отправителя, адрес и порт получателя) и есть некий такой TCP-адрес, адрес уровня транспорта, идентификатор, вернее так. TCP. Да.

Почему лектор говорит, что порт это такой переходный уровень между TCP и уровнем приложений? Дело в том, что согласно некоторой договорённостям, разные типы приложений сидят на разных портах, можем ожидать, как интерпретировать данные, которые посыпятся на определенный порт, т.е. при подключении по 80 порту то что мы передаем будет интерпретироваться как HTTP-запросы, а по порту 22 нас ждет Secure Shell. Почему так? Да потому что никакого другого способа указать клиенту, по какому порту как подключаться, мы не имеем. Мы можем, конечно, словами сказать, вот у меня есть сервер, ты подключайся, пожалуйста, по порту 9090. Лектор на стриме завёл барахло, на 9090 порту, кто знал, тот ходил.

Существует организация IANA, в которой вы можете зарегистрировать своё приложение, сказав: пускай теперь такой-то порт теперь исключительно вот для этого используется. (cat /etc/services). Known ports, так называемые. Как вы могли заметить, временный порт выбирается достаточно большим, кажется он должен быть больше 32000, есть такая традиция, в некоторых случаях это нужно.

Вопросы

В чём разница между TCP-пакетами и UDP-датаграммами?

В них нет почти ничего общего. Нет, ip и порт есть, даже порт отправителя, что удивительно. Если на прикладном уровне не сделано своей поддержки подтверждений, мы можем свой udp-пакет послать вникуда, и он уйдёт вникуда, есть класс задач, где только так себя и нужно вести, например широковещание, не хватало нам от всех клиентов, которые смотрят наше потоковое видео, получать подтверждения и сообщения об ошибках, и обрабатывать их. Другая область применения, когда сам факт обмена данных заключается в посылке очень маленьких пакетов, а сама работа на прикладном уровне подразумевает, что будет отчет, типичный пример -- это dns, незачем из одного пакета делать 4. И если мы ждем ответа от dns-сервера, то его можно ждать и на прикладном уровне, с тем же успехом, как ждать установления tcp-соединения. Траффик экономится, и чем выше уровень DNS-сервера, тем выгоднее экономить его. Сетевые файловые системы, NFS, раньше использовали UDP. Тут забавная ситуация. Если у вас очень медленный (по времени ответа) канал, то в действительности по нему удобно гонять, как ни странно, именно udp. Надо оценивать, в том числе и случай возникновения ошибки, т.к. если мы узнаем о ней поздно, то уже можем успеть послать много лишних пакетов. В современности среды передачи данных работают все быстрее, компьютеры работают еще быстрее, а надёжность не повышается, на 1000 пакетов один зажёвывается. И получается, что с установлением соединения теперь получается быстрее.

{03:27:40}


Сведения о ресурсах

Готовность (%)

Продолжительность (ак. ч.)

Подготовка (календ. ч.)

Полный текст (раб. д.)

Предварительные знания

Level

Maintainer

Start date

25

1

1

1

1

(кто?), DmitryChistikov

03.07.2008