Я читал различные сайты и обучающие онлайн, но я все еще смущен. Если сообщение больше IP MTU, то send()
возвращает отправленный байт. Что происходит с остальной частью сообщения? Могу ли я снова позвонить send()
и попытаться отправить остальную часть сообщения? Или что-то IP-слой должен заботиться автоматически?TCP/UDP и ethernet MTU Фрагментация
ответ
Если вы используете TCP, тогда представленный вам интерфейс представляет собой поток байтов. Вам не нужно беспокоиться о том, как поток байтов поступает с одного конца соединения на другой. Вы можете игнорировать MTU уровня IP. На самом деле вы можете полностью игнорировать IP-уровень.
Когда вы вызываете send()
, стек TCP на вашем компьютере будет обрабатывать все данные, необходимые для потока байтов, который вы нажимаете на свои вызовы отправки, чтобы появляться с recv()
вызовов на другом конце соединения.
Единственное, что нужно помнить о том, что с TCP вы имеете дело с потоком, и это означает, что один send()
может привести к получению данных, поступающих в нескольких recv()
звонков и несколько send()
вызовов может привести к получению данных, поступающих в одном recv()
вызова. У вас нет контроля над этим. Вы имеете дело с потоком байтов, и каждый вызов recv()
может возвращать любое количество байтов от 1 до числа, которое в настоящее время неактивно (с учетом наличия достаточного количества буферов, переданных на вызов recv()
).
Поскольку комментаторы напросились;)
На большинстве TCP стеки send()
, скорее всего, не сможет отправить все, потому что буфера стека TCP пестреют и (возможно) окно TCP также полное и поток управления что стеки не могут отправлять больше данных, пока удаленный конец не подаст какие-либо данные, и он не подготовлен к тому, чтобы больше буферизовать от вашего имени. Я не встречал стек TCP, который откажет send()
из-за одних только соображений MTU, но я предполагаю, что некоторые похудела встроенные системы могут вести себя таким образом ...
Во всяком случае, если send()
возвращает меньше, чем число байтов, вы предоставили его, тогда вы должны повторно отправить оставшиеся данные в какой-то момент. Часто send()
блокирует и ждет, пока он не сможет отправить все данные, и если вы установили сокет в неблокирующий режим, вы, вероятно, НЕ хотите немедленно повторить отправку, если он не сможет отправить все, как вы, вероятно, закончите в плотно закрытой петле ...
Возможно, вам было бы более полезно узнать о операционной системе, которую вы используете.
Если пакет слишком велик для транзита сети, то намек на фрагментацию ICMP отправляется сигналу отправителя, чтобы уменьшить размер пакета и повторить попытку.
Если вы используете TCP, это все детали, которые вы должны ожидать, чтобы сетевой уровень позаботился о вас. Какие современные стеки IP фактически делают за кулисами, чтобы понять, что самый низкий MTU вдоль пути, похоже, стал черным искусством.
WRT UDP вы все еще можете ожидать, что стек будет фрагментировать для вас, но практически предоставил прецедент для UDP, что не является идеальным. В зависимости от вашего приложения вы, скорее всего, увидите лучшую производительность, явно понимая путь MTU.
... на вопрос send() некоторые стеки ведут себя по-другому, но обработка WRT вашего кода должна быть одинаковой. Допустим, у вас есть 100 байт для отправки ... send() возвращает отправленные 10 байт.Вам нужно продолжать звонить посылкой с оставшимися 90 байтами, пока он не вытолкнет провод для отправки всего сообщения.
Использование блокирующих сокетов на платформе Windows send() будет автоматически возвращаться после того, как все отправлено. На других платформах .. Linux и др. Вам нужно будет чаще отправлять отправку данных.
+1, но для завершения вы также должны иметь дело с тем, что представляет наибольший интерес для вопроса: если значение, возвращаемое 'send', меньше запрошенных байтов (очень маловероятный случай, поскольку стек попытается чтобы справиться с этим), вы несете ответственность за отправку остальной части данных позднее, если это необходимо. –
Действительно ли это маловероятно? Поскольку я, кажется, получает меньшее значение, возвращаемое 'send()', чем запрошенные байты, чтобы отправлять все время, когда запрошенный байт превышает MTU. –
Unix в. Но вы ответили на мой вопрос подробно. Большое спасибо!! –