Отключение алгоритма Nagle на стороне клиента /JavaScript
Нужно ли отключать алгоритм Nagle на стороне клиента? Если это так, я не нашел способа отключить алгоритм Нейгла только через JavaScript.
Я пытаюсь передавать данные через веб-сокет с сервера CLI PHP, размещенного на Raspbian OS (также размещенного на Windows 7 и Ubuntu с такими же результатами). Этот сервер успешно создал сокет и принимает несколько соединений и установил флаг TCP_NODELAY (проверяется только с socket_get_option).
$sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)
socket_set_option($sock, SOL_SOCKET, TCP_NODELAY, 1);
На большинстве платформ, независимо от того, установлен этот флаг TCP_NODELAY, данные будут передаваться без слипания. Однако в Windows 7 Chrome и Firefox данные поступают порциями (с задержкой 0,2 с). В Windows 8, Linux, iOS и Windows 7 Internet Explorer 11: я вообще не вижу этой проблемы.
http://www.13willows.com/hovelme/script/serverControl.php Вот тестовый веб-сайт, нажмите "Подключиться", затем нажмите "Просмотр игры", и вы должны видеть, что текущий пакет постоянно увеличивается от 1 до 20 каждые 50 мс., Тем не менее, на некоторых клиентах он скачет на 4 за раз примерно каждые 200 мс.
Есть идеи, чтобы остановить это? Будет ли использование node.js / socket.io исправлять что-то подобное и все же позволит мне запускать код из браузера пользователя?
2 ответа
По крайней мере, Chrome, похоже, отключает алгоритм Nagle для всех сокетов WebSocket:
Стоит отметить, что Chrome также отключает алгоритм Nagle на всех своих TCP-сокетах.
Но похоже, что опция NODELAY должна быть включена с обеих сторон, чтобы гарантировать низкую задержку:
Мы уже отключили Nagle на всех платформах, используя именно такой метод, но это не отключает задержку ACK (или, по крайней мере, не отключает в Windows, вполне возможно, где-то еще).
Исходный код Chromium, кажется, подтверждает это (но я не разработчик Chromium, поэтому я просто предполагаю, что следующий код вызывается для всех сокетов TCP, как сказал один из комментаторов выше):
void TCPSocketPosix::SetDefaultOptionsForClient() {
DCHECK(socket_);
// This mirrors the behaviour on Windows. See the comment in
// tcp_socket_win.cc after searching for "NODELAY".
// If SetTCPNoDelay fails, we don't care.
SetTCPNoDelay(socket_->socket_fd(), true);
// TCP keep alive wakes up the radio, which is expensive on mobile. Do not
// enable it there. It's useful to prevent TCP middleboxes from timing out
// connection mappings. Packets for timed out connection mappings at
// middleboxes will either lead to:
// a) Middleboxes sending TCP RSTs. It's up to higher layers to check for this
// and retry. The HTTP network transaction code does this.
// b) Middleboxes just drop the unrecognized TCP packet. This leads to the TCP
// stack retransmitting packets per TCP stack retransmission timeouts, which
// are very high (on the order of seconds). Given the number of
// retransmissions required before killing the connection, this can lead to
// tens of seconds or even minutes of delay, depending on OS.
#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
const int kTCPKeepAliveSeconds = 45;
SetTCPKeepAlive(socket_->socket_fd(), true, kTCPKeepAliveSeconds);
#endif
}
См. Также эту возможную идею обходного пути - /questions/25899581/tcp-paketyi-websocket-obedinyayutsya/25899599#25899599
Это нужно включить / отключить на обоих клиентах, однако я не знаю, как это сделать с помощью javascript; для клиентов. Я считаю, что Chrome отключает его по умолчанию для веб-сокетов, но не уверен в других браузерах.