Всем привет! Сегодня будет довольно графичная статейка, поясняющая, как будет производится передача данных в локальных сетях с привлечением протоколов различного уровня.
Исходная ситуация
Итак, вначале мы имеем некое приложение, которому нужно отправить данные в другое приложение. Пусть исходный Узел 1 захотел передать что-то на Узел 2. IP адреса соответственно 192.168.1.1 и .2. Согласно схеме…
Поэтапная передача пакета
- Узел 1. (Прикладной уровень) “Мне нужно передать данные на 192.168.1.2 на порт 2099, надежность доставки не требуется!”.
- Узел 1. (Транспортный уровень) “Окей, подойдёт UDP протокол, давай сюда свои данные”.
- Узел 1. (Прикладной уровень) “На, держи! [0xFF,0xFF, 0x01, …., 0x2E, 0x47]” — произвольные 16-ричные данные. (далее <данные>)
- Узел 1. (Транспортный уровень) “Отлично. Прикреплю-ка я к ним заголовок UDP, чтобы не потерять пакет. В заголовке зафиксируем некоторые данные и номера портов. Какой там свободный? UDP:42133! Отлично. А порт назначения UDP:2099. Такой заголовок и прикрепим. Спускаем пакет дальше, на сетевой уровень. (Пакет: [<заголовок транспортного уровня><данные>]
- Узел 1. (Сетевой уровень) “Получил ваш пакет, куда передавать? На IP:192.168.1.2? Прикреплю к этому заголовку ещё и информацию сетевого уровня. Ну и свой обратный IP: 192.168.1.1 и ещё некоторую информацию от себя… Эй, канальный уровень! Тут для тебя пакет!”. [<заголовок сетевого уровня><заголовок транспортного уровня><данные>]
- Узел 1. (Канальный уровень) “Оп-па. Пакет. А куда доставить? Смотрим по заголовку… Такс, на 192.168.1.2. Хммм.. Не помню адреса MAC, связанного с этим IP, гляну в таблице коммутации apr… Хм. Нет такого адреса у меня пока. Будем запрашивать у среды. Пакет пока отложим.”
- (парковка пакета)
- Узел 1. (Канальный уровень) “Эй, среда! Есть в сети кто-то с 192.168.1.2? Ответьте на мой MAC: 0001.43B7.623C! У меня для вас пакет! Физический уровень, передай это плз.!”
- Узел 1. (Физический уровень) Рассылается вышеуказанный широковещательный пакет всем станциям (на адрес FFFF.FFFF.FFFF)Каждая станция в широковещательном домене получит этот пакет и проигнорирует его в том случае, если её IP отличается от IP в этом пакете. Станция же, чей IP-адрес совпадает с указанным ответит встречным пакетом.
- Коммутатор. “Я получил кадр со стороны порта 1. Анализирую назначение. О! Широковещательный кадр. Отправлю его на все остальные порты кроме того, откуда он пришёл. На всякий случай запомню, что на первом порту у меня [0001.43B7.623C]”.
- Узел 3. (Физический) “Я получил широковещательный кадр. Канальный, передаю”.
- Узел 3. (Канальный) “Получил. Эй, сетевой! там спрашивают IP 192.168.1.2, а у нас 192.168.1.3. Игнорируем.”
- Узел 2. (Физический) “Я получил широковещательный кадр. Канальный! Передаю тебе”.
- Узел 2. (Канальный уровень) “Понял! О! Это для меня! Физический, телеграфируй обратно следующее: Послушай, 0001.43B7.623C! Это я! У меня IP адрес 192.168.1.2! Запомни мой MAC 0004.9A41.0966 у себя в таблице коммутации. И не забудь про пакет!”.
- Коммутатор. “Я получил кадр со стороны порта 2. для MAC: 0001.43B7.623C. Судя по таблице, он у меня на стороне порта 1. Передам кадр в этот порт. А попутно сохраню адрес 0004.9A41.0966 как адрес на стороне порта 2, пригодится”.
- Узел 1. (Канальный уровень) “Нашёлся обладатель адреса 192.168.1.2. Теперь я прикреплю к пакету адрес назначения [0004.9A41.0966], а так же свой обратный MAC [0001.43B7.623C] и отдам на физический уровень для передачи. Физический! Держи пакет!”. [<заголовок канального уровня><заголовок сетевого уровня><заголовок транспортного уровня><данные>]
- Узел 1. (Физический уровень) “Ок.”
- Коммутатор. “Оп-па, получил кадр для MAC: 0004.9A41.0966. Он у меня со стороны порта 2. Посылаю кадр туда”.
- Узел 2. (Физический уровень) “Принял кадр. Передаю на канальный уровень”. [<заголовок канального уровня><заголовок сетевого уровня><заголовок транспортного уровня><данные>]
- Узел 2. (Канальный) “Так, пришел пакет от 0001.43B7.623C. Действительно для меня. А в нем какие-то данные протокола IP. Это не моя тема, я уберу заголовок своего уровня и отдам выше, на сетевой”.[<заголовок сетевого уровня><заголовок транспортного уровня><данные>]
- Узел 2. (Сетевой) “Какой-то пакет от IP 192.168.1.1, а в нем какие-то данные транспортного уровня. Пакет для IP: 192.168.1.2, передам в соответствующий интерфейс, пусть там разбираются транспортники”.[<заголовок транспортного уровня><данные>]
- Узел 2. (Транспортный) “Пришел пакет от сетевого, там данные для порта 2099, висит какой-то сервис, ждёт пакет. Передайте!” [<данные>]
- Узел 2. (Прикладной) “Урра! Данные для меня!. Спасибо за внимание ^_^”
Класс! Все разжевано до мелочей, по-больше бы таких статей в инете. Есть вопрос – на прикладном уровне с UDP все отлично – что отправил то и получил, а вот TCP исходя из последовательности может разбиться по кускам. Тут предлагают юзать какието TLV маркеры: https://bovs.org/post/170/Peredaca-paketov-cerez-potok-TCP , что вы по этому поводу думаете? Как лучше пакетировать траффик поверх TCP?
Насколько я понимаю TLV это просто структура данных tag, length, value. То есть метка, длина данных и сами данные. Мы берём некоторый объём данных, разделяем его на фрагменты, чтобы без проблем входили в размер сегмента (MSS) с учётом тега и поля длины, вычисляем длину каждого сегмента и записываем структуру. Каждый сегмент данных метим определённым тегом так, чтобы был понятен порядок их сборки. Допустим мы разделили данные, пометили их тегом вида A1, A2, A3, A4 и т.д., передаём в произвольном порядке. На принимающей стороне собираем эти сегменты по порядку A1, A2, A3, A4, отделяем теги и по полю размер данных собираем последовательность и получаем исходные данные. Само-собой, другие потоки данных передаём с тегами B1, B2, B3 и C1, C2, C3 и т.д. Таким образом можно передавать сразу множество потоков в разном порядке и в итоге на принимающей стороне собирать их в зависимости от тега в конкретные структуры. Это вариант. Примерно по такому принципу работает p2p протоколы типа торрентов и т.д.
Моё видение
Здравствуйте. Скорее всего в Вашей статье ошибка. После рисунка:
“Каждая станция в широковещательном домене получит этот пакет и проигнорирует его в том случае, если её MAC отличается от MAC в этом пакете. Станция же, чей MAC-адрес совпадает с указанным ответит встречным пакетом.”
Может речь идет не о MAC адпесе, а об IP адресе? MAC адрес в этом пакете широковещательный. MAC адрес у 192.168.1.2 еще только должны узнать.
Тоже самое 12 пункт: “Узел 3. (Транспортный) “Получил. Так, там спрашивают MAC 0004.9A41.0966, а у меня 0010.1194.5972. Игнорируем.””
Должно быть “… а у меня 192.168.1.3”
Вы правы, внёс необходимые корректировки! И да, там не транспортный, а канальный уровень – с mac-адресами работает.