Является ли успешный send () "атомным"? - PullRequest
4 голосов
/ 07 ноября 2011

Гарантирует ли успешный вызов send () с возвращенным числом, равным сумме, указанной в параметре размера, «частичные отправки» не произойдет?

Или есть какой-то способ, которым ОС может быть прервана во время обслуживания системного вызова, отправить часть данных, подождать, возможно, долгое время, а затем отправить остальные и вернуться, не сообщив мне меньшее возвращаемое значение? *

Я не говорю о случае, когда недостаточно места в буфере ядра; Я понимаю, что тогда получу меньшее возвращаемое значение и попробую снова.

Обновление: На основании полученных ответов мой вопрос можно перефразировать следующим образом:

Есть ли способ отправки пакетов / данных по сети до возврата вызова send ()?

Ответы [ 2 ]

5 голосов
/ 07 ноября 2011

Успешный вызов метода send () с возвращаемым числом, равным сумме, указанной в> параметре размера, гарантирует, что "частичная отправка" не произойдет?

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

Или существует какая-либо причина, по которой ОС может быть прервана при обслуживании системыВызов, отправить часть данных, подождать, возможно, долгое время, затем отправить остальные и вернуться, не уведомив меня с меньшим возвращаемым значением?

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

(Это крайнеНапример, большинство стеков TCP защищает от отправки таких небольших сегментов данных одновременно, но то же самое применимо, если вы пытаетесь отправить 4k данных, но одноранговый узел имеет место только для 3k).

I 'я не говорю о случае, когда в буфере ядра недостаточно места;Я понимаю, что тогда я получу меньшее возвращаемое значение и попытаюсь повторить

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

Изменить для ответа:

Есть ли способ отправки пакетов / данных по проводной сети до того, как вызов send () вернется?

Да.Это может случиться по многим причинам.например,

  • Локальные буферы заполняются этим недавним вызовом send (), и вы используете блокирующий ввод / вывод.
  • Стек TCP отправляет ваши данные по проводам, но решает:запланировать выполнение других процессов до того, как процесс отправки вернется из send ().
3 голосов
/ 07 ноября 2011

Хотя это зависит от протокола, который вы используете, общий вопрос: нет .

Для TCP данные буферизуются внутри ядра, а затем отправляются по усмотрению TCPАлгоритм пакетирования, который довольно сложный - он хранит несколько таймеров, пытаясь избежать MT фрагментации IP-адресов.

Для UDP вы можете предполагать такого рода «атомарность», только если ваша дейтаграмма не превышает размер кадра ссылкиобычное значение - 1472 = 1500 кадров Ethernet - 20 байтов заголовка IP - 8 байтов заголовка UDP).В противном случае отправляющему хосту придется IP-фрагментировать дейтаграмму.

Тогда промежуточные маршрутизаторы все еще могут IP-фрагментировать проходящий пакет, если MTU их исходящей линии связи меньше размера пакета.

...