Подтвердить что ты не робот

Есть ли существенная разница между TCP_CORK и TCP_NODELAY в этом случае?

После написания ответа о TCP_NODELAY и TCP_CORK я понял, что моих знаний о тонких точках TCP_CORK, должно быть, не хватает, так как это не на 100% не понятно, почему Linux разработчики считали необходимым ввести новый флаг TCP_CORK, а не просто полагаться на приложение для установки или очистки существующего флага TCP_NODELAY в соответствующие моменты времени.

В частности, если у меня есть приложение Linux, которое хочет отправить() некоторые мелкие/несмежные фрагменты данных по потоку TCP, не оплачивая налог на задержку в течение 20 месяцев, и в то же время минимизирует количество пакетов необходимо отправить его, я могу сделать это одним из двух способов:

С TCP_CORK (псевдокодом):

int optval = 1;
setsockopt(sk, SOL_TCP, TCP_CORK, &optval, sizeof(int));   // put a cork in it
send(sk, ..);
send(sk, ..);
send(sk, ..);
optval = 0;
setsockopt(sk, SOL_TCP, TCP_CORK, &optval, sizeof(int));   // release the cork

или с TCP_NODELAY (псевдокодом):

int optval = 0;
setsockopt(sk, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof(int));   // turn on Nagle's
send(sk, ..);
send(sk, ..);
send(sk, ..);
optval = 1;
setsockopt(sk, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof(int));   // turn Nagle back off

Я использую последнюю технику в течение многих лет с хорошими результатами, и она также может быть переносимой для ОС, отличной от ОС Linux (хотя за пределами Linux вам нужно снова позвонить send() после того, как Nagle отступит, чтобы обеспечить немедленное отправку пакетов и избежать достаточного количества нулевых байтов с помощью Nagle-delay().

Теперь разработчики Linux - умные ребята, поэтому я сомневаюсь, что вышеупомянутое использование TCP_NODELAY им никогда не приходило в голову. Должна быть какая-то причина, по которой они считали, что этого недостаточно, что привело к тому, что вместо этого они представили новый/собственный флаг TCP_CORK. Может ли кто-нибудь объяснить, в чем причина?

4b9b3361

Ответ 1

У вас есть два вопроса:

  • Есть ли существенная разница между TCP_CORK и TCP_NODELAY в этом прецеденте?
  • Должна быть какая-то причина, по которой они считали, что этого недостаточно, что привело к тому, что вместо этого они представили новый/собственный флаг TCP_CORK. Может ли кто-нибудь объяснить, в чем причина?

Сначала просмотрите ответы в этом Вопрос о переполнении стека, поскольку они связаны с тем, поскольку этот вопрос в целом описывает разницу между этими двумя без ссылки на ваш usecase.

  • TCP_NODELAY ON означает отправку данных (частичных кадров) в тот момент, когда вы получаете, независимо от того, у вас достаточно кадров для полного сетевого пакета.
  • TCP_NODELAY OFF означает Nagles Algoritm, который означает отправку данных, когда он больше, чем MSS, или ожидает подтверждения приема, прежде чем отправлять данные, которые меньше.
  • TCP_CORK ON означает, что не отправлять какие-либо данные (частичные кадры) меньше, чем MSS, пока приложение не скажет так или до 200 мс позже.
  • TCP_CORK OFF означает отправку всех данных (частичных кадров).

Это означает, что в вашем примере использования в первом примере никакие частичные кадры не отправляются до конца, но в вашем втором примере будут отправлены частичные кадры с подтверждением приема.

Также окончательная передача в первом примере, алгоритм Nagle по-прежнему применяется к частичным кадрам после откупоривания, где, как и во втором примере, это не так.

В короткой версии TCP_NODELAY отправляет не накапливает логические пакеты перед отправкой, а затем в качестве сетевых пакетов алгоритм Nagle выполняет алгоритм, а TCP_CORK выполняет в соответствии с настройкой приложения.

Побочным эффектом этого является то, что алгоритм Nagle отправит частичные кадры на незанятое соединение, TCP_CORK не будет.

Дополнительно TCP_CORK был введен в ядро ​​Linux в 2.2 (в частности, 2.1.127 см. здесь), но до 2.5.71 он был взаимно эксклюзивно с TCP_NODELAY. Например, в ядрах 2.4 вы можете использовать один или другой, но в версии 2.6 вы можете комбинировать два, а TCP_CORK будет иметь приоритет при его применении.

Относительно вашего второго вопроса.

Процитировать Линус Торвальдс

Теперь TCP_CORK в основном я рассказываю Дэвиду Миллеру, что я отказываюсь играть игры, чтобы иметь хорошее распределение размера пакета, и что я хотел, чтобы приложение просто скажет ОС: я хочу большие пакеты, пожалуйста, подождите, пока вы получаете от меня достаточное количество данных, чтобы создавать большие пакеты.

В принципе, TCP_CORK - это своего рода флаг "anti-nagle". Это обратное "Нет-Нэйгл".

Еще одна цитата, сделанная Linus относительно использования TCP_CORK, следующая

В принципе, TCP_CORK полезен, когда сервер знает шаблоны его массовые переводы. Это примерно в 100% случаев с любым видом файл.

Для получения дополнительных котировок см. ссылку с Диспетчером рассылки Sendfile.

В целом, помимо TCP_MAXSEG и MSGMORE при вызове writev, TCP_CORK - это еще один инструмент, который позволяет приложению в пользовательском пространстве иметь более мелкозернистый контроль над распределением размера пакета.

Ссылки и дальнейшее чтение