web-dev-qa-db-ja.com

ChromeでのWebSocketと、1分間の非アクティブ後のFirefox切断

ChromeとFirefoxが1分間非アクティブになった後に切断されます。オンラインで見たものに基づいて、プロキシやサーバー設定などを非難する設定になりましたが、これは、IEまたはEdgeでは発生しません。IEおよびEdgeだけに適用される非アクティブな状態が1分間続くと、サーバーによってソケットが切断されるようです。 ChromeとFirefox。

これがなぜだれか知っていますか?どこに文書化されていますか?私はpingでそれを止める方法を知っていますが、なぜそれが起こっているのかに興味があります。切断時に表示される理由コードは1006で、ブラウザが接続を閉じたことを示します。エラーはスローされず、ソケットのonerrorイベントはトリガーされません。

このプロジェクトは https://glitch.com/edit/#!/noiseless-helmet で構築され、すべてを確認して実行できます。クライアントページは次の場所にあります。 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>

Node.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);
});
11
user12861

IEとEdgeと同じくらいChromeとFirefox。

うーん、いや、そうではない。 IE and Edgemightは、WebSocketプロトコルの一部としてpingパケットを実装しています。

WebSocketプロトコルには、プロトコルレベルpingのサポートが含まれています JavaScript APIが公開していません。これは、多くの場合実装されるユーザーレベルのpingよりも少し低レベルです。

このping-pongトラフィックは、すべてのネットワーク仲介者(プロキシ、ロードバランサーなど)のタイマーをリセットします。そして、常に接続を閉じて古い接続をマークします(たとえば、- Herokuのセットアップ時間は55秒で接続 )。

ほとんどのブラウザは、サーバーがpingを実装することを信頼しています。これはポライトです(サーバーはpingの負荷とタイムアウトを管理する必要があるため...

...しかし、接続が異常に失われたかどうかはブラウザにはわからないため、少しイライラします。多くのJavaScriptクライアントがユーザーレベルのping(つまり、JSON {event: "ping", data: {...}}または別の「空の」イベントメッセージ)。

とにかく、私はあなたの仮定が間違っていたことを指摘したかったのですが、これはまだタイムアウトが発生しているため、ブラウザの動作の違いはおそらくブラウザ自体に関連しています。

Nginxのデフォルトのタイムアウトに関するいくつかの詳細(WebSocket接続をプロキシする場合)については、@ Hendryの答えを読むことができます。

6
Myst

WebSocketプロトコル仕様では、キープアライブ、ハートビート、ネットワークステータスの調査に使用できるPingおよびPongフレームが定義されています。 Pingは、クライアント/サーバーがiqを送信して、接続を維持するように反対側のサーバー/クライアントに通知し、反対側も確認応答を送信することを意味しますpongが同じペイロードデータを持つ場合。

ブラウザが応答を停止したとき、または停止したと見なされるときのタイムアウトを定義することもできます。

続きを読む: http://vunse.blogspot.in/2014/04/websocket-ping-pong.html

4
Sakshi Nagpal

私がこれを調査して理解した限りでは、これは、データが送信されていない期間にわたってタイムアウトするwebsocketによって引き起こされます。これはおそらくブラウザごとです。

Pingを使用してこれを解決するか、ソケットを再度使用する必要があるときに再接続することができます。

ブラウザ側のようにサーバー側から使用されていないソケットを開いたままにしないことは理にかなっています。たとえば、Chromeには、接続数を64個に制限し、64個のタブを開いている場合、開くことができる接続の数に制限があります(これは、私が常に多くのタブ各タブがサーバーに接続されているため、これ以上接続できませんでした(Chromeで使用可能なソケットを使い果たしたときに、実際に同じようなことが起こりました)。

WebSocket接続にも適用されるproxy_read_timeout( http://nginx.org/r/proxy_read_timeout )があります。バックエンドが長時間何も送信しない場合は、バンプする必要があります。あるいは、websocket pingフレームを定期的に送信してタイムアウトをリセットするようにバックエンドを構成することもできます(そして、接続がまだ生きているかどうかを確認します)。

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

Webソケットのアイドルタイムアウトは60秒です:pingやpongフレーム経由でハートビートなどを使用しない場合、ソケットはユーザーがページを閉じ、ソケットを閉じてリソースを節約します。

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

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

4
Hendry