2010-09-23 311 views
54

我正在使用使用PHP5和Chrome瀏覽器作爲客戶端的Web套接字。 我已將網站的代碼記錄下來。服務器在WebSocket中重新啓動時重新連接客戶端

我運行服務器,客戶端也連接。我也可以聊天。 現在,當我重新啓動服務器(通過將其重新啓動並重新啓動服務器)時, 客戶端將獲取斷開連接的信息,但是當我發送消息時,它自動不會與服務器重新連接。

如何實現這一目標?就像我收到斷開連接的信息一樣,我是否應該檢查並將其發送到JavaScript以刷新頁面或重新連接?

回答

95

當服務器重新啓動時,Web Socket連接關閉,因此將觸發JavaScript onclose事件。這是一個嘗試每五秒重新連接的示例。

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); 
    }; 
} 
+0

我有同樣的問題和解決方案的工作非常出色。感謝名單! – 2011-12-01 13:50:00

+1

你應該在這裏使用一個匿名函數:'function(){start(websocketServerLocation)}'而不是一個字符串,所以你不會觸發'eval()' – 2012-06-22 20:15:08

+2

我希望有更優雅的方式,而不需要構造一個新的對象並定義事件動作... – ciembor 2013-02-10 23:05:27

29

安德魯給出的解決方案是不完美的工作,因爲在失去連接的情況下,服務器可能會發送多個關閉事件。

在這種情況下,你會設置幾個setTimout的。如果服務器在五秒鐘之前準備就緒,Andrew提供的解決方案可能只能工作。

然後,根據安德魯解決方案,返工,我利用的setInterval的ID附加到window對象(這種方式它是可用「無處不在」):

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 */ 
/* ... */ 
} 
16

我一直在用這個有一段時間是純粹的香草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事件發生時未啓動,則該連接在其恢復聯機後仍會恢復。

注意:使用此腳本不會允許您永遠停止嘗試打開連接......但我認爲這就是您想要的?

+5

我只會改變: 函數檢查(){ if(!ws || ws.readyState === WebSocket.CLOSED)start(); } – dieresys 2016-07-19 17:33:31

+0

這種方法,加上這裏描述的keep-alive技術(http://www.jstips.co/en/javascript/working-with-websocket-timeout/),似乎對我很好。 – Peter 2018-01-19 17:19:06

3

以下是我在我的項目中使用的代碼,其工作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(); }; 
} 
21

ReconnectingWebSocket

GitHub上託管該裝飾的WebSocket的API提供一個WebSocket連接,如果連接中斷,將自動重新連接一個小型的JavaScript庫。

使用gzip壓縮的縮小庫小於600字節。

官方資料庫,請訪問:

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

服務器水災

如果當它重新啓動大量的客戶端連接到服務器。 通過使用指數退避算法來管理客戶端的重新連接時間可能是值得的。

該算法是這樣的:

  1. 對於k的嘗試中,生成0和2之間的時間的隨機間隔^的k - 1,
  2. 如果能夠重新連接,復位k以1
  3. 如果重新連接失敗,由1 k增加,並且在步驟1中的過程重新開始,
  4. 要截斷的最大間隔,當已經達到嘗試k的一定數,k停止每次嘗試後增加。

參考:

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

ReconnectingWebSocket不處理利用該算法重新連接。

+3

https://github.com/gamestdio/websocket.js使用指數退避 – vgoklani 2016-05-19 11:43:42

+0

很好的答案,尤其是因爲它提到服務器關閉Web套接字連接後服務器負載過高的風險,並且所有客戶端(可能是數百或成千上萬)嘗試同時重新連接。除了指數退避之外,您還可以隨機化0到10秒之間的延遲。這也會將負載分散到服務器上。 – 2017-03-17 15:03:35

0

不能發表評論,但以下幾點:

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已經足夠好:)

相關問題