Является ли успешный send() "атомарным"?


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

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

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

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

Существует ли способ передачи пакетов/данных по проводу до того, как вызов send() вернется?

2 4

2 ответа:

Гарантирует ли успешный вызов функции send() с возвращенным числом, равным сумме, указанной в параметре >the size, что не произойдет" частичной отправки"?

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

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

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

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

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

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

Изменить, чтобы ответить:

Существует ли способ передачи пакетов/данных по проводу до того, как вызов send() вернется?

Да. Это может произойти по многим причинам. например

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

Хотя это зависит от используемого протокола, общий вопрос - Нет.

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

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

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