Чи можна пакети TCP та UDP розділити на частини?


41

Чи можуть пакети TCP надходити до приймача по шматках?

Наприклад, якщо я надсилаю 20 байт за допомогою протоколу TCP, чи можу я бути на 100% впевнений, що я отримаю рівно 20 байтів, а не 10 байт, а потім ще 10 байт чи так?

І те саме питання для протоколу UDP.
Я знаю, що UDP недостовірний, і пакети взагалі не можуть надходити або надходити в іншому порядку, але як бути з одним пакетом? Якщо він надійде, чи можу я бути впевнений, що це повний пакет, а не шматок?


7
Пояснення: Він називається сегментом TCP та дейтаграмою UDP. Вони не є пакетами. TCP = Сегмент, UDP = Datagram, IP = Пакет, Ethernet = Кадр, На всіх інших шарах (AFAIK) їх просто називають PDU (Unit Data Unit).
joeqwerty

Відповіді:


33

Чи можуть пакети TCP надходити до приймача по шматках?

Так. IP підтримує фрагментацію, хоча TCP, як правило, намагається визначити MTU шлях і зберегти його пакети меншими за показник продуктивності. Фрагментація катастрофічно збільшує рівень втрат дейтаграми. Якщо шлях має 10% -ву швидкість втрати пакетів, фрагментація дейтаграми на два пакети робить показник втрати дейтаграми майже 20%. (Якщо загублений будь-який пакет, дейтаграма втрачається.)

Вам не доведеться турбуватися з цього приводу, як і рівень TCP. IP-рівень знову збирає пакети в цілі дейтаграми.

Наприклад, якщо я надсилаю 20 байтів за допомогою протоколу TCP, чи можу я бути на 100% впевнений, що я отримаю рівно 20 байтів, а не 10 байт, а потім ще 10 байт?

Ні, але це не має нічого спільного з пакетами. TCP - це, по суті, протокол байтового потоку, який не зберігає меж повідомлення програми.

І те саме питання для протоколу UDP. Я знаю, що UDP ненадійний, і пакети взагалі не можуть надходити або надходити в іншому порядку,

Те саме стосується TCP. Пакети - це пакети. Різниця полягає в тому, що у протоколу TCP є вбудовані повторення та упорядкування, а UDP - не.

а як щодо 1 пакета? Якщо він надійде, чи можу я бути впевнений, що це повний пакет, а не шматок?

Ні, але це не ваша проблема. Протокол UDP обробляє збірку дейтаграми. Це частина його роботи. (Насправді протокол IP робить це для протоколу UDP, тому UDP робить це лише шляхом шаруватості поверх IP). Якщо дейтаграма розбивається на два пакети, протокол IP повторно зіставить її для протоколу UDP, тож ви побачать повні дані.


10
Можливо, варто буде уточнити останній біт для початківців читачів: ви побачите повні дані для даної дейтаграми . Якщо будь-який з пакетів розділення втрачається, дейтаграма втрачається, і рівень UDP ніколи про це не дізнається. Поки всі пакети в дейтаграмі будуть отримані, вони будуть зібрані на рівні IP та потім передані до рівня UDP. Це не виключає можливості відсутності "фрагментів" у потоці даних. Щоб не бути педантом, але, коли я вивчав цей матеріал, я не збагнув різниці між фрагментами IP та втратою UDP, поки 2-й чи 3-й не пройдуть підручник.
Джастін ᚅᚔᚈᚄᚒᚔ

20

Ви не можете бути впевнені, що вони дійсно фізично приїжджають одразу. Шари зв’язків даних нижче TCP / UDP можуть розділити ваш пакет, якщо вони хочуть. Особливо, якщо ви надсилаєте дані через Інтернет або будь-які мережі, що не є вашими, це важко передбачити.

Але незалежно від того, чи надійдуть дані в одному або декількох пакетах на приймачі. ОС повинна абстрагувати конкатенацію цих пакетів, тому для вашого додатку все одно виглядає все, що надійшло відразу. Тож, якщо ви не хакер ядра, у більшості випадків вам не потрібно хвилюватися, якщо ці дані передаються в одному або декількох пакетах.

Для UDP ОС також буде робити деяку абстракцію, тому додаток, який отримує дані, не повинен знати, скільки пакетів даних передано. Але різниця від TCP полягає в тому, що гарантії фактичного надходження даних немає. Можливо також, що дані розбиваються на кілька пакетів, а деякі надходять, а деякі - ні. Для приймаючої програми вона все одно виглядає як потік даних, незалежно від того, повна вона чи ні.


Чи не драйвер мережевої карти не піклується про повторну збірку пакетів, а не ядра?
bluehallu

2
@Hallucynogenyc: Якщо все не зміниться, протокол Інтернету розроблений так, що дозволяє розбивати пакети понад 576 байтів у будь-яку точку їхньої подорожі, однак не очікує, що їх, крім кінцевого одержувача, їх рекомбінувати. Думаю, ідея полягає в тому, що використання більшої кількості пакетів було в більшості випадків зусиллям для зменшення витрат; Після того, як пакет був розбитий в якийсь момент своєї подорожі, накладні витрати вже були здійснені, так що рекомбінація перед тим, як кінцевий одержувач не зможе нічого допомогти, і може зашкодити, якщо його доведеться повторно розділити.
supercat

Я вважаю, що хоча будь-який пакет, який перевищує 576 байтів, може бути розділений, але пакети, менші за цей розмір, можуть не бути; вбудовані системи, які не можуть мати справу з розділеними пакетами, не повинні запитувати нічого більшого.
supercat

1
@ mauro.stettler: Я написав стек TCP на "голому металі" (написання коду для прямого спілкування з кількома мікросхемами мережевого інтерфейсу). Для апаратних засобів, що спілкуються на посилання з 576-байтним лімітом для розділення довших пакетів, просто. Перекомпонування пакетів набагато складніше, тим більше, що можна отримати шматочки багатьох різних пакетів до того, як будь-який з них буде отриманий в повному обсязі.
supercat

Існує деяка надія , що вона не буде розколом для маленьких корисних навантажень (близько 10 або 20 байт повинні бути в порядку), тому що є «гарантується максимальний розмір» потрібно для кожного стрибка для IP paquets на ipv4: по крайней мере , 68 байт (включаючи IP-заголовки, не враховуючи заголовків нижнього рівня). дивіться першу таблицю в en.wikipedia.org/wiki/Maximum_transmission_unit . Відмінна від 576 байт мінімального розміру, необхідного для хостів (тобто початковий або кінцевий момент передачі, а не всі посередники). І обережно: корисна навантаження все ще нижча (оскільки заголовки кожного шару займають певний простір).
Олів'є Дулак

14

Приклади. Блоки суміжних символів відповідають викликам send ():

TCP:

Send: AA BBBB CCC DDDDDD E         Recv: A ABB B BCC CDDD DDDE

Усі надіслані дані отримуються в порядку, але не обов'язково в одних шматках.

UDP:

Send: AA BBBB CCC DDDDDD E         Recv: CCC AA E

Дані необов'язково в одному порядку і взагалі не обов'язково отримуються, але повідомлення зберігаються в повному обсязі.


5

Наприклад, якщо я надсилаю 20 байтів за допомогою протоколу TCP, чи можу я бути на 100% впевнений, що я отримаю рівно 20 байтів, а не 10 байт, а потім ще 10 байт?

Ні, TCP є протоколом потоку, він зберігає дані в порядку, але не групує їх за повідомленням. З іншого боку, UDP орієнтований на повідомлення, але ненадійний. SCTP володіє кращими з обох світів, але не є оригінальним для використання, оскільки NAT розбиває Інтернет.


1

Існує певна впевненість, що якщо ви надішлете 20 байт на самому початку потоку TCP, він не отримає як два 10 байтних фрагмента. Це відбувається тому, що стек TCP не надсилатиме такі невеликі сегменти: мінімальний розмір MTU. Однак якщо відправка знаходиться десь посеред потоку, усі ставки відміняються. Можливо, ваш стек протоколів займає 10 байт даних, щоб заповнити сегмент і відправити його, а потім наступні десять байт переходять до іншого сегмента.

Ваш стек протоколів розбиває дані на шматки і розміщує їх у черзі. Розміри шматка базуються на шляху MTU. Якщо ви виконуєте операцію надсилання, і все ще є очікування даних у черзі, стек протоколів, як правило, зазирне в сегмент, який знаходиться в кінці черги, і побачить, чи є в цьому сегменті місце для додавання більше даних. Кімната може бути розміром як один байт, так що навіть двобайтове надсилання можна розбити на два.

З іншого боку, сегментація даних означає, що можуть бути часткові читання. Операція прийому може потенційно прокинутися і отримати дані, коли надійде лише один сегмент. У широко реалізованому API сокетів виклик прийому може запитати 20 байт, але він може повернутися з 10. Звичайно, на ньому може бути побудований буферний шар, який буде блокувати, поки не буде отримано 20 байтів, або з'єднання не буде розірвано. У світі POSIX цей API може бути стандартними потоками вводу / виводу: ви можете fdopenописувати сокет для отримання FILE *потоку, і ви можете використовувати freadйого для заповнення буфера таким чином, щоб повний запит був задоволений стільки readвикликів, скільки потрібно .

Даніграми UDP обрамляють дані. Кожен виклик відправки генерує дейтаграму (але див. Нижче про виправлення). Інша сторона отримує повну дейтаграму (і в API сокета він повинен вказати буфер, достатньо великий, щоб вмістити його, інакше дейтаграма буде усічена). Великі дейтаграми розбиваються на фрагментацію IP і прозоро перебираються у додатки. Якщо якийсь фрагмент відсутній, вся дейтаграма втрачається; у цій ситуації немає можливості прочитати часткові дані.

Існують розширення інтерфейсу, що дозволяють декільком операціям вказувати одну дейтаграму. У Linux сокет можна «закупорити» (не можна надсилати). Поки він пробковий, письмові дані збираються в єдине ціле. Тоді, коли сокет буде "відключений", може бути надіслана одна дейтаграма.


це помилково: якщо один надіслати пакет з корисним навантаженням 10 або 20 байт, це генерує 1 пакет, і (як я вже говорив вище), якщо використовується ipv4, він повинен, навіть додаючи всі заголовки інших шарів протоколу, відповідати в межах 68 байт, гарантуючи таким чином, що він проходить через усі переходи в 1 пакеті. Tcp стек не буде (як натякано у вашому 1-му абзаці) "зачекайте, поки mtu заповнений (тобто додайте кілька пакетів, щоб зробити належний розмір)", щоб надіслати пакет! ... Це поводиться, що порушить багато речей ( навіть якщо ці "фрагменти" були надіслані від & до тієї самої пари господарів)
Олів'є Дулак

@OlivierDulac: Це неправильно. TCP, як правило, генерує пакети, намагаючись оптимізувати використання мережі, тому 20 байт може закінчитися двома різними пакетами, як пояснив Kaz. Це можна контролювати за допомогою параметра socket TCP_NODELAY , яка відключає алгоритм Nagles, який розсилає байти до пакетів, якщо вашій програмі потрібна швидша мережа TCP. Крім того, 68 байт аж ніяк не є фактичним стандартом для довжини пакету: 1500 байт - більш звичайне значення за замовчуванням (це дійсно залежить від мереж).
jjmontes
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.