WebSockets в Chrome и Firefox отключается после одной минуты бездействия

я обнаружил, что WebSockets в Chrome и Firefox отключаются ровно через одну минуту бездействия. Основываясь на том, что я видел в Интернете, я был настроен обвинять прокси или некоторые настройки сервера или что-то еще, но этого не происходит в IE или Edge. Похоже, что если сокеты отключены сервером после одной минуты бездействия, это будет применяться к IE и Edge так же, как Chrome и Firefox.

кто-нибудь знает почему это? Это где-нибудь задокументировано? Я знаю возможный способ остановить это, пингуя, но меня больше интересует, почему это происходит. Код причины, указанный при отключении, равен 1006, что указывает на то, что браузер закрыл соединение. Ошибки не возникают, и событие onerror для сокета не запускается.

этот проект был построен в https://glitch.com/edit/#!/бесшумный шлем!8--> где вы можете увидеть и запустить все. Страница клиента обслуживается здесь: https://noiseless-helmet.glitch.me/

вот моя страница клиента:

<div id="div">
</div>
<script>
  let socket = new WebSocket("wss://noiseless-helmet.glitch.me/");
  socket.onmessage = function(event) {
    div.innerHTML += "<br>message " + new Date().toLocaleString() + " " + event.data;
  };
  socket.onopen = function (event) {
    div.innerHTML += "<br>opened " + new Date().toLocaleString();
    socket.send("Hey socket! " + new Date().toLocaleString());
  };
  socket.onclose = function(event) {
    div.innerHTML += "<br>socket closed " + new Date().toLocaleString();
    div.innerHTML += "<br>code: " + event.code;
    div.innerHTML += "<br>reason: " + event.reason;
    div.innerHTML += "<br>clean: " + event.wasClean;
  };
  socket.onerror = function(event) {
    div.innerHTML += "<br>error: " + event.error;
  };
</script>

и вот мой узел.сервера JS код:

var express = require('express');
var app = express();
app.use(express.static('public'));

let server = require('http').createServer(),
  WebSocketServer = require('ws').Server,
  wss = new WebSocketServer({ server: server });

app.get("/", function (request, response) {
  response.sendFile(__dirname + '/views/index.html');
});

let webSockets = [];
wss.on('connection', function connection(socket) {
  webSockets.push(socket);
  webSockets.forEach((w) => { w.send("A new socket connected"); });
  socket.on('close', (code, reason) => {
    console.log('closing socket');
    console.log(code);
    console.log(reason);
    let i = webSockets.indexOf(socket);
    webSockets.splice(i, 1);
  });
});

server.on('request', app);
server.listen(process.env.PORT, function () {
  console.log('Your app is listening on port ' + server.address().port);
});

3 ответов


похоже, что если сокеты отключены сервером после одной минуты бездействия, которые будут применяться к IE и Edge так же, как Chrome и Firefox.

Хммм, нет, это не так. IE и Edge может провести ping пакет как часть протокола WebSocket.

протокол WebSocket включает поддержку уровня протокола ping что API JavaScript не предоставляет. Это немного ниже уровня чем пользовательский уровень pinging, который часто реализуется.

этой ping-pong трафик сбрасывает таймеры в любых сетевых посредниках (прокси, балансировщики нагрузки и т. д.) - И они все время подключаются, чтобы отметить устаревшие соединения для закрытия (например,Heroku время установки соединения на 55 секунд).

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

...однако это также немного расстраивает, так как браузеры понятия не имеют, было ли соединение ненормально потеряно. Вот почему многие клиенты JavaScript реализуют пользовательский уровень ping (т. е. json {event: "ping", data: {...}} или другое "пустое" сообщение о событии).

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

в течение нескольких особенности таймаутов по умолчанию nginx (при проксировании соединений WebSocket) вы можете прочитать ответ @Hendry.


спецификация протокола WebSocket определяет кадры пинг-понга, которые могут быть использованы для поддержания жизни, сердцебиения, зондирования состояния сети. Ping означает, что клиент / сервер отправляет iq, чтобы сообщить другому серверу/клиенту, что для поддержания соединения, а также другая сторона отправит подтверждение с понг имея те же данные полезной нагрузки.

вы также можете определить тайм-аут, когда браузер перестает отвечать или рассматриваться мертвый.

подробнее:http://vunse.blogspot.in/2014/04/websocket-ping-pong.html


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

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

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

есть когда (http://nginx.org/r/proxy_read_timeout) что также относится к подключениям WebSocket. Вы должны поднять если ваш сервер не отправить все, что угодно, на долгое время. Кроме того, вы можете настроить свой бэкэнд для отправки websocket ping кадры периодически сбрасывать тайм-аут (и проверить, если соединение все еще живо).

https://forum.nginx.org/read.php?2,236382, 236383#msg-236383

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

https://www.codeproject.com/Questions/1205863/Websocket-is-closed-after-min

https://github.com/tornadoweb/tornado/issues/1070