Сокет "Flush" путем временного включения NoDelay - PullRequest
5 голосов
/ 02 апреля 2011

Фон

У меня есть реализация HTTP-сервера на C #. Используя ab , я обнаружил странную проблему с производительностью. Каждый запрос занимал 5 мс с отключенным Keep-Alive, но 40 мс с включенным Keep-Alive!

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

Причина в том, насколько я могу судить об алгоритме Нагла, используемом в стеке TCP.

TCP Flush?

Пока что я использую свойство NoDelay в конце каждого обслуживаемого HTTP-запроса.

socket.NoDelay = true;
socket.NoDelay = false;

Который сейчас решает проблему. Но у меня нет документации для резервного копирования моего открытия.

Это было проверено в системе linux / mono.

Существует ли стандартный способ очистки TCP-соединения?

Относящиеся

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

Ответы [ 4 ]

6 голосов
/ 18 июля 2011

Я проверил это с Wireshark. К сожалению,

socket.NoDelay = true;
socket.NoDelay = false;

не имеет никакого эффекта. Аналогичным образом,

socket.NoDelay = true;
socket.Send(new byte[0]);
socket.NoDelay = false;

также не имеет никакого эффекта. Из наблюдаемого поведения видно, что свойство NoDelay влияет только на следующий вызов Send с непустым буфером. Другими словами, вам нужно отправить некоторые фактические данные, прежде чем NoDelay окажет какое-либо влияние.

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

Однако, поскольку вы пишете HTTP-сервер, вы можете использовать несколько приемов:

  • Для запросов, которые обслуживаются с помощью Transfer-Encoding: chunked, вы можете отправить маркер конца потока ("\r\n0\r\n\r\n") с помощью NoDelay = true.
  • Если вы обслуживаете файл из локальной файловой системы, вы будете знать, когда файл закончится, поэтому вы можете установить NoDelay = true непосредственно перед отправкой последнего фрагмента.
  • Для запросов, которые обслуживаются с использованием Content-Encoding: gzip, вы можете установить NoDelay = true непосредственно перед закрытием потока gzip; поток gzip отправит несколько последних битов перед фактическим завершением и закрытием.

Я, безусловно, добавлю вышеупомянутое на мой HTTP-сервер сейчас:)

2 голосов
/ 02 декабря 2018

Если вы знаете длину данных, которые вы отправляете, настройка SendBufferSize заставит сокет отправлять данные сразу, следующий пример рабочего кода:

byte[] bytesToSend = ASCIIEncoding.ASCII.GetBytes(message);
socket.SendBufferSize = bytesToSend.Length;
socket.Send(bytesToSend);
1 голос
/ 03 мая 2011

Написав довольно популярный веб-сервер, я не думаю, что Nagle algortihm - ваша настоящая проблема.

Как вы строите свои ответы и как их отправляете?

0 голосов
/ 02 апреля 2011

Нет такой вещи, как очистка в TCP. TCP - это потоковый протокол, который группирует / разгруппирует / разделяет / объединяет ваши данные. Отключение nagle будет делать это реже.

Не отключать nagle.

Алгоритм Nagle TCP / IP был разработан, чтобы избежать проблем с маленькими пакеты, называемые крошечными, на медленных сетей. Алгоритм говорит, что Соединение TCP / IP может иметь только одно выдающийся небольшой сегмент, который не имеет еще не был признан. Определение «маленький» меняется, но обычно это определяется как «меньше, чем сегмент размер "который в сети Ethernet составляет около 1500 байт.

Посмотрите здесь: Отключение алгоритма TCP / IP Nagle повышает скорость при медленных сетях

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...