WebSocketを正しく閉じる(HTML5、JavaScript)


127

私はHTML5 WebSocketをいじっています。私はどうやって接続を優雅に閉じるのですか?たとえば、ユーザーがページを更新したり、ブラウザを閉じたりするとどうなりますか?

ユーザーが呼び出しをせずにページを更新しただけでは奇妙な動作が発生しますwebsocket.close()-更新後に戻ったときにwebsocket.oncloseイベントにヒットします。

回答:


110

よるプロトコル仕様(現在サポートしているブラウザに実装することバージョン)V76:

接続をきれいに閉じるには、1つのピアから0xFFバイトとそれに続く0x00バイトだけで構成されるフレームを送信し、他のピアが接続を閉じるように要求します。

サーバーを作成している場合は、サーバーがクライアント接続を閉じるときに必ず終了フレームを送信する必要があります。通常のTCPソケットクローズメソッドは遅くなる場合があり、アプリケーションが接続が開いていなくてもまだ開いているとアプリケーションに思わせる可能性があります。

ブラウザーは、ページを閉じるか再読み込みするときに、これを実際に行う必要があります。ただし、beforeunloadイベントをキャプチャーすることで、クローズフレームが送信されたことを確認できます。

window.onbeforeunload = function() {
    websocket.onclose = function () {}; // disable onclose handler first
    websocket.close();
};

ページが更新された後、oncloseイベントを取得する方法がわかりません。ページがリロードされると、WebSocketオブジェクト(oncloseハンドラー付き)は存在しなくなります。ページの読み込み時にすぐにページ上でWebSocket接続を確立しようとしている場合、古い接続が切断された直後(またはブラウザの準備ができていない)にサーバーが新しい接続を拒否するという問題が発生している可能性があります接続しようとしている時点で接続を確立します)、新しいwebsocketオブジェクトのoncloseイベントを取得しています。


2
Firefoxでは、接続が次のページの読み込みにハングアップしているように見える可能性があります。参照が見つかりませんが、これに関するバグがあった可能性があります。もう1つの可能性はonclose、ユーザーがナビゲートしたりページをリロードしたときに、イベントが予期せず、または意図的にトリガーされた可能性があります。私がしました質問投稿権利とどのように我々は、自動再接続を実装し、それを持っているブラウザ期待される動作がどうあるべきか尋ねると、。
レゲッター

4
イベントでこれらの問題を検討してくださいonbeforeunload
artkoenig


35

今日のWebSocketには2つの主要なプロトコルバージョンが使用されています。[0x00][message][0xFF]プロトコルを使用する古いバージョンと、Hybi形式のパケットを使用する新しいバージョンがあります

古いプロトコルバージョンはOperaおよびiPod / iPad / iPhoneで使用されているため、WebSocketサーバーに下位互換性を実装することが実際に重要です。これらのブラウザーで古いプロトコルを使用していると、ページを更新したり、ページから移動したり、ブラウザーを閉じたりすると、ブラウザーが自動的に接続を閉じることがわかりました。すごい!!

ただし、新しいプロトコルバージョン(Firefox、Chrome、最終的にはIE10など)を使用するブラウザーでは、ブラウザーを閉じるだけでブラウザーが自動的に接続を閉じます。つまり、ページを更新したり、ページから移動したりしても、ブラウザは自動的に接続を閉じません。ただし、ブラウザが行うことは、最初のバイト(proto ident)が0x88(close data frameとして知られている)であるサーバーにhybiパケットを送信することです。サーバーがこのパケットを受信すると、必要に応じて接続自体を強制的に閉じることができます。


4
サーバー側での実際の例では、このhybiパケットを管理する方法を教えてください。
albanx 2013年

9
接続を閉じないのは正気ではないようです。WebSocket変数はページの再読み込み時に消去されるので、アクセスできない場合に接続が開いたままになるのはなぜですか?接続を再利用しても意味がありません。
Triynko 2013

@albanx以下の私の答えを確認してください
artkoenig

Websocketクライアント(ブラウザなど)から閉じるフレームを送信する方法のコードサンプル。私はws npmモジュールを使用しています
Shaik Syed Ali

3

theoobeで述べたように、一部のブラウザはWebSocketを自動的に閉じません。クライアント側で「ブラウザウィンドウを閉じる」イベントを処理しようとしないでください。現在、主要なデスクトップおよびモバイルブラウザのサポートを検討している場合(たとえばonbeforeunload、Mobile Safariでは機能しない)、信頼できる方法はありません。私はこの問題をサーバー側で処理する経験が豊富でした。たとえば、Java EEを使用している場合は、javax.websocket.Endpointを見てください。ブラウザに応じて、OnCloseメソッドまたはOnErrorメソッドは、ブラウザウィンドウを閉じるか再ロードすると呼び出されます。


1
私の場合、データ転送中にConnectionが閉じられます。OperaやiOSファミリーのブラウザーの場合はうまく機能します。私を助けてください..私は過去2週間以来、この問題と戦っています。stackoverflow.com/q/30799814/2225439
Mrug

2

Webソケットのcloseメソッドを使用して、要件に応じて任意の関数を記述できます。

var connection = new WebSocket('ws://127.0.0.1:1337');
    connection.onclose = () => {
            console.log('Web Socket Connection Closed');
        };
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.