Максимальний розмір пакета для з'єднання TCP


197

Який максимальний розмір пакета для з'єднання TCP або як я можу отримати максимальний розмір пакета?


24
TCP - це потік. Чи є певна причина, що ви турбуєтесь про окремі пакети?
Матті Вірккунен

27
Оскільки шари під ним базуються на пакеті ... Типова реалізація -> Шар 1 - Ethernet PHY, рівень 2 - Ethernet MAC (визначення пакету MAC, рівень 3 - Інтернет-протокол (визначення пакета IP)), рівень 4 - TCP (протокол управління передачею) ) - Використовує сервіс на основі пакетів під ним.

2
Немає такого поняття, як "пакет TCP". Є сегменти TCP , довжина яких описується 32-бітним словом, і вони містяться всередині або через IP- пакети, довжина яких описана у 16 ​​бітах. Є також кадри Ethernet, в яких містяться всі ці речі. Про яку з цих речей ви питаєте? У будь-якому випадку, якщо ви використовуєте TCP, вам ні в якому разі не потрібно хвилюватися про будь-який з них: TCP та IP доглядають за вами.
Маркіз Лорн

Відповіді:


178

Абсолютне обмеження на розмір пакета TCP становить 64 К (65535 байт), але на практиці це набагато більше, ніж розмір будь-якого пакета, який ви побачите, оскільки нижчі шари (наприклад, Ethernet) мають менші розміри пакетів.

Наприклад, MTU (блок максимальної передачі) для Ethernet становить 1500 байт. Деякі типи мереж (наприклад, Token Ring) мають більші MTU, а деякі типи мають менші MTU, але значення фіксуються для кожної фізичної технології.


15
"Але значення фіксуються для кожної фізичної технології" - це неправда. У Ethernet раніше було максимальна MTU 1500, але ви могли використовувати нижчу. З появою джамбо-кадрів не існує реального заданого максимуму, а максимум змінюється в залежності від обладнання та драйвера.
WhirlWind

4
@Whirl: правда, вони налаштовуються, але, як правило, вони не є; "налаштовується" є суб'єктивним, оскільки для цього потрібно було б заглибитися в ядро. Це не те, з чим можна попрацювати на рівні програми, саме там, схоже, знаходиться ОП.
Ефір

3
@HiroProtagonist: 1500 - це максимум, тому мати 600 - це не дивно.
Ніколя Рауль

28
чому це обмеження на 64 К (65535 байт)? Оскільки атрибут "Розмір вікна" в заголовку TCP становить лише 16 біт. Я просто хотів згадати, чи можу я колись допомогти ..... чудова відповідь btw @Ether!
Cacho Santa

2
Також можна збільшити його за допомогою масштабування вікон. У цьому випадку максимум - 1 Гб
Мартін Мелька,

86

Це відмінне запитання, і я дуже часто на цьому стикаюся на роботі. Є багато "технічно правильних" відповідей, таких як 65k і 1500. Я багато працював над написанням мережевих інтерфейсів, і використання 65k нерозумно, і 1500 також може привести вас до великих проблем. Моя робота триває безліч різних апаратних / платформ / маршрутизаторів, і якщо чесно, я починаю 1400 байт. Якщо вам потрібно більше 1400, ви можете почати збільшувати свій шлях вгору, ймовірно, ви можете піти на 1450, а іноді і на 1480'іш? Якщо вам потрібно більше, ніж тоді, звичайно, вам потрібно розділити на 2 пакети, з яких є кілька очевидних способів зробити ..

Проблема полягає в тому, що ви говорите про створення пакету даних і записування його через TCP, але, звичайно, є дані заголовка, які вписані і так далі, тому у вас є "багаж", який ставить вас до 1500 або більше .. а також Багато обладнання має нижчі межі.

Якщо "натиснути", ви можете зробити деякі справді дивні речі. Обрізані дані, очевидно, або скинуті дані я бачив рідко. Пошкоджені дані також рідко, але, безумовно, трапляються.


Чому GET-запити в середньому становлять близько 600 байт?

10
Ви маєте на увазі 64K, а не 65K. Я не знаю, що ви маєте на увазі під "місцем, з якого я починаю, - 1400 байт". Вам не доведеться турбуватися про розміри пакетів в API TCP. Він дбає про визначення та дотримання шляху MTU. Немає причини, чому ви не можете написати 2G в одному, send()якщо це зручно.
Маркіз Лорн

19
Ваше 1480'ishмає бути 1460. IP-заголовок та заголовок TCP займають щонайменше по 20 байт (якщо не використовуються необов'язкові поля заголовка), і, таким чином, максимум для (не кадрів Jumbo) Ethernet є 1500 - 20 -20 = 1460.
Євген Бересовський

2
Я через Wireshark бачив, що сервер надсилає великі пакети (понад 1400 байт), і клієнт отримує його в розібраному вигляді на кілька пакетів максимумом 1400 байт. хто відповідає за демонтаж пакета? @Nektario ...?
inbaly

2
@EugeneBeresovsky добре з додатковими заголовками thats + до 40 більше байтів, але він мінливий, тому 1420, здавалося б, межа. з пропозицією 1400 ви отримуєте трохи підкладки. Я піду з 1408, оскільки це ділиться на 128
Гарет Клаборн

22

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

TCP займається сегментами, а не пакетами. Кожен сегмент TCP має порядковий номер, який міститься всередині заголовка TCP. Фактичні дані, що надсилаються в сегменті TCP, є змінними.

Існує значення для getsockopt, яке підтримується в деяких ОС, які ви можете використовувати під назвою TCP_MAXSEG, яке отримує максимальний розмір сегмента TCP (MSS). Він підтримується не у всіх ОС.

Я не впевнений, що саме ви намагаєтесь зробити, але якщо ви хочете зменшити розмір буфера, який використовується, ви також можете вивчити: SO_SNDBUF та SO_RCVBUF.


Цікаво, чи можете ви використовувати TCP як чергу повідомлень, чи зможете ви помістити всі ваші повідомлення у великий пакет TCP?
CMCDragonkai


4

У API TCP немає пакетів.

Часто в базових протоколах є пакети, як, наприклад, коли TCP робиться через IP, до якого ви не зацікавлені, оскільки вони не мають нічого спільного з користувачем, за винятком дуже делікатних оптимізацій продуктивності, які вас, мабуть, не цікавлять (відповідно до формулювання питання).

Якщо ви запитаєте, яка максимальна кількість байтів ви можете send()в одному дзвінку API, то це залежить від реалізації та налаштувань. Зазвичай ви закликаєте send () для шматок до кількох кілобайт, і завжди будете готові до того, що система відмовиться прийняти її повністю або частково, і в цьому випадку вам доведеться вручну керувати розділенням на менші шматки, щоб подати свої дані в TCP send () API.


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

23
@WhirlWind TCP має сегменти. IP має пакети.
Маркіз Лорн

1
TCP має сегменти (або називайте їх пакетами, це нормально). TCP API не має пакетів.
Павло Радзівіловський

13
@NathanLong Шкода полягає в тому, що ви викликаєте непотрібну плутанину. TCP має сегменти, UDP має дейтаграми, IP має пакети, Ethernet має кадри, ...
Маркіз Лорн

1
@Chexxor Отже, якою мовою ви будете користуватися для опису сегментів TCP всередині IP-пакетів всередині Ethernet-кадрів? Немає ніякої необхідності плутати проблему, використовуючи один і той же термін для різних речей, коли автори цих речей зіткнулися з великими труднощами, використовуючи різні терміни.
Маркіз Лорнський

3

Як правило, це залежатиме від інтерфейсу, який використовується з'єднання. Можливо, ви можете використовувати ioctl (), щоб отримати MTU, а якщо це ethernet, зазвичай ви можете отримати максимальний розмір пакету, віднявши від нього розмір апаратного заголовка, який становить 14 для Ethernet без VLAN.

Це лише в тому випадку, якщо MTU принаймні така велика по всій мережі. TCP може використовувати відкриття MTU для зменшення ефективної MTU.

Питання в тому, навіщо вам байдуже?


6
Це отримає лише максимальний розмір пакета на першому посиланні. Наскільки мені відомо, будь-який інший вузол по маршруту може не любити великі пакети, і він може розколотися в будь-якому місці шляху.
Матті Вірккунен

Так, це правда ... тож ваше запитання добре - навіщо б ви цього хотіли?
WhirlWind

Я хочу передати відео / зображення через локальне з'єднання
Alexa

1
Оскільки TCP орієнтований на потоки, чому це має значення?
WhirlWind

3

Якщо ви працюєте з машинами Linux, "ifconfig eth0 mtu 9000 up" - це команда встановити MTU для інтерфейсу. Однак, мушу сказати, великий MTU має деякі недоліки, якщо передача мережі не настільки стабільна, і вона може використовувати більше пам’яті простору ядра.


3

Здається, більшість веб-сайтів в Інтернеті використовують 1460 байт для вартості MTU. Іноді це 1452, і якщо ви перебуваєте на VPN, він зменшиться ще більше для заголовків IPSec.

Розмір вікна за замовчуванням досить варіюється до максимуму 65535 байт. Я використовую http://tcpcheck.com для перегляду значень IP власного джерела та для перевірки того, чим користуються інші Інтернет-постачальники.


2

Одним з рішень може бути встановлення параметра socket TCP_MAXSEG ( http://linux.die.net/man/7/tcp ) на значення, яке є "безпечним" для базової мережі (наприклад, встановити 1400 для безпечного використання в Ethernet), а потім використовувати великий буфер для відправки системного виклику. Таким чином може бути менше системних дзвінків, які є дорогими. Ядро розділить дані на відповідність MSS.

Таким чином ви можете уникнути усічених даних, і вашій програмі не потрібно турбуватися про невеликі буфери.


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.