web-dev-qa-db-ja.com

サーバーがWebSocketで再起動したときのクライアントの再接続

PHP5とChrome=ブラウザをクライアントとして使用してWebソケットを使用しています。サイトからコードを取得しました http://code.google.com/p/phpwebsocket/

サーバーを実行すると、クライアントも接続されます。私もチャットできます。サーバーを(再起動して)再起動すると、クライアントは切断された情報を取得しますが、メッセージを送信してもサーバーと自動的に再接続しません。

これを達成する方法は?切断された情報を取得したときのように、それを確認し、JavaScriptに送信してページを更新するか、再接続する必要がありますか?

85
siddhusingh

サーバーが再起動すると、Web Socket接続が閉じられるため、JavaScript oncloseイベントがトリガーされます。以下は、5秒ごとに再接続を試みる例です。

function start(websocketServerLocation){
    ws = new WebSocket(websocketServerLocation);
    ws.onmessage = function(evt) { alert('message received'); };
    ws.onclose = function(){
        // Try to reconnect in 5 seconds
        setTimeout(function(){start(websocketServerLocation)}, 5000);
    };
}
133
Andrew

Andrewが提供するソリューションは、接続が失われた場合にサーバーがいくつかの終了イベントを送信する可能性があるため、完全に機能していません。

その場合、いくつかのsetTimoutを設定します。 Andrewが提供する解決策は、サーバーが5秒前に準備ができている場合にのみ機能します。

次に、Andrewのソリューションに基づいて作り直し、setIntervalを使用してIDをウィンドウオブジェクトにアタッチしました(その方法で "どこでも"使用可能です)。

var timerID=0;

var socket;

/* Initiate what has to be done */

socket.onopen=function(event){
 /* As what was before */
 if(window.timerID){ /* a setInterval has been fired */
   window.clearInterval(window.timerID);
   window.timerID=0;
 }
 /* ... */
}

socket.onclose=function(event){
  /* ... */
 if(!window.timerID){ /* Avoid firing a new setInterval, after one has been done */
  window.timerID=setInterval(function(){start(websocketServerLocation)}, 5000);
 }
 /* That way, setInterval will be fired only once after losing connection */
 /* ... */
}
38
user2909737

WebSocketの再接続

GitHubは、接続が切断された場合に自動的に再接続するWebSocket接続を提供するためにWebSocket APIを修飾する小さなJavaScriptライブラリをホストします。

Gzip圧縮の縮小ライブラリは600バイト未満です。

公式リポジトリは次の場所にあります。

https://github.com/joewalnes/reconnecting-websocket

サーバーフラッド

再起動時に多数のクライアントがサーバーに接続されている場合。指数バックオフアルゴリズムを使用して、クライアントの再接続タイミングを管理する価値がある場合があります。

アルゴリズムは次のように機能します。

  1. K回の試行の場合、0〜2 ^ k-1のランダムな時間間隔を生成します
  2. 再接続できる場合は、kを1にリセットします
  3. 再接続に失敗した場合、kは1増加し、プロセスはステップ1から再開します
  4. 最大間隔を切り捨てるために、特定の試行回数kに達すると、試行ごとにkの増加が停止します。

参照:

http://blog.johnryding.com/post/78544969349/how-to-reconnect-web-sockets-in-a-realtime-web-app

ReconnectingWebSocketは、このアルゴリズムを使用した再接続を処理しません。

31
Joël Esponde

私はしばらくこのバトンを純粋なバニラJavaScriptに使用してきましたが、他の回答よりもいくつかのケースをサポートしています。

document.addEventListener("DOMContentLoaded", function() {

  'use strict';

  var ws = null;

  function start(){

    ws = new WebSocket("ws://localhost/");
    ws.onopen = function(){
      console.log('connected!');
    };
    ws.onmessage = function(e){
      console.log(e.data);
    };
    ws.onclose = function(){
      console.log('closed!');
      //reconnect now
      check();
    };

  }

  function check(){
    if(!ws || ws.readyState == 3) start();
  }

  start();

  setInterval(check, 5000);


});

これは、サーバーが接続を閉じるとすぐに再試行し、接続を確認して、5秒ごとに接続が確立されていることを確認します。

そのため、これが実行されたとき、またはoncloseイベントの時点でサーバーが稼働していない場合、接続がオンラインに戻った後も接続は再び戻ります。

注:このスクリプトを使用しても、接続を開こうとするのを止めることはできません...しかし、私はそれがあなたが望むものだと思いますか?

26
complistic

以下は、100%動作するプロジェクトで使用したコードです。

  1. すべてのwebsocketコードをinit関数内に配置します。
  2. Oncloseコールバック内で、initを再度呼び出します。
  3. 最後に、ドキュメント準備関数内でinit関数を呼び出します。

var name = sessionStorage.getItem( 'name');

wsUri =  "ws://localhost:8080";   
var websocket;
$(function() {  
    init();  
    $("#chat_text_box").on("keypress", function(e) {         
        if (e.keyCode == 13) {   //For Enter Button    
            e.preventDefault();
            var mymessage = $('#chat_text_box').val();               
            if(mymessage){
                var msg = {  type: 'chat_text',  data : {  name:name,  msg:mymessage }  };                
                console.log(msg);
                websocket.send(JSON.stringify(msg));
                $('#chat_text_box').val('');
            }               
            return false;                       
        }        
    });      
});     
function init() { 
    websocket = new WebSocket(wsUri);      
    websocket.onopen = function(ev) { /*connection is open */    } 
    websocket.onmessage = function(ev) {        
        var data = JSON.parse(ev.data); //PHP sends Json data        
        var type = data.type;//alert(JSON.stringify(data));
        switch(type) {
            case "chat_text":
                var text = "<div><span class='user'>"+data.data.sender_name+" : </span><span class='msg'>"+data.data.msg+"</span></div>";
                $('#chat-messages').append(text);
                break;            
            default:
                break;

        }        

    };     
    websocket.onerror   = function(ev){}; 
    websocket.onclose = function(ev) {   init();   };  
}
2
Pradeepta

コメントはできませんが、次のとおりです。

var socket;

const socketMessageListener = (event) => {
  console.log(event.data);
};

const socketOpenListener = (event) => {
  console.log('Connected');
  socket.send('hello');
};

const socketCloseListener = (event) => {
  if (socket) {
    console.error('Disconnected.');
  }
  socket = new WebSocket('ws://localhost:8080');
  socket.addEventListener('open', socketOpenListener);
  socket.addEventListener('message', socketMessageListener);
  socket.addEventListener('close', socketCloseListener);
};

socketCloseListener();

// for testing
setTimeout(()=>{
  socket.close();
},5000);

プラス https://www.npmjs.com/package/back はすでに十分です:)

2
xemasiv