Фрагментация TCP / UDP и Ethernet MTU - PullRequest
3 голосов
/ 09 марта 2010

Я читал различные сайты и учебники в Интернете, но я все еще в замешательстве.Если сообщение больше, чем IP MTU, то send() возвращает отправленный байт.Что происходит с остальной частью сообщения?Должен ли я снова позвонить send() и попытаться отправить оставшуюся часть сообщения?Или это то, что IP-уровень должен позаботиться автоматически?

Ответы [ 2 ]

6 голосов
/ 09 марта 2010

Если вы используете TCP, то представленный вам интерфейс - это поток байтов.Вам не нужно беспокоиться о том, как поток байтов попадает с одного конца соединения на другой.Вы можете игнорировать MTU уровня IP.На самом деле вы можете полностью игнорировать уровень IP.

Когда вы звоните send(), стек TCP на вашем компьютере будет обрабатывать все детали, необходимые для потока байтов, который вы отправляете в ваши вызовы отправки, чтобы появиться из вызовов recv() на другом концесоединение.

Единственное, что нужно помнить, это то, что с TCP вы имеете дело с потоком, и это означает, что один send() может привести к тому, что данные поступят в несколько вызовов recv(), а несколько вызовов send() могутВ результате данные поступают в один вызов recv().Вы не можете это контролировать.Вы имеете дело с потоком байтов, и каждый вызов recv() может возвращать любое количество байтов от 1 до номера, ожидающего в настоящее время (с учетом адекватных буферов, передаваемых на вызов recv()).

ПосколькуКомментаторы попросили об этом;)

В большинстве стеков TCP send(), скорее всего, не сможет отправить все, потому что буферы стека TCP заполнены и (вероятно) окно TCP также заполнено, и управление потоком работаетЭто означает, что стек не может отправлять больше данных до тех пор, пока удаленный конец не подтвердит получение некоторых данных, и он больше не готов к буферизации от вашего имени.Я не сталкивался со стеком TCP, который будет отказываться от send() только из-за соображений MTU, но я предполагаю, что некоторые уменьшенные встроенные системы могут вести себя таким образом ...

В любом случае, если send() возвращает меньшечем количество байтов, которые вы предоставили, то вам следует повторно отправить оставшиеся данные в какой-то момент.Часто send() будет блокировать и ждать, пока он не сможет отправить все данные, и если вы установили сокет в неблокирующий режим, то вы, вероятно, НЕ хотите немедленно повторять отправку, если она не может отправить все, так как выСкорее всего, это окажется в узком цикле ...

Возможно, вам было бы полезно более подробно рассказать об используемой операционной системе.

0 голосов
/ 09 марта 2010

Если пакет слишком велик для транзита по сети, отправляется подсказка фрагментации ICMP, сигнализирующая отправителю уменьшить размер пакета и повторить попытку.

Если вы используете TCP, это все детали, которые вы должны ожидать от сетевого уровня. То, что современные IP-стеки на самом деле делают за кулисами, чтобы выяснить самый низкий MTU на пути, похоже, стало черным искусством.

WRT UDP вы все еще можете ожидать, что стек фрагментируется для вас, но практически, учитывая вариант использования UDP, он не идеален ... в зависимости от вашего приложения вы, вероятно, увидите более высокую производительность, явно понимая MTU пути.

... на вопрос send () некоторые стеки ведут себя по-разному, но обработка вашего кода WRT должна быть такой же. Допустим, у вас есть 100 байтов для отправки ... send () возвращает отправленные 10 байтов. Вы должны продолжать вызывать send с оставшимися 90 байтами, пока все не вытолкнет провод для отправки всего сообщения.

Использование блокирующих сокетов на платформе Windows send () обычно возвращает после того, как все отправлено .. На других платформах ... Linux и др. Вам придется продолжать отправлять чаще, чтобы отправить данные.

...