我正在使用使用PHP5和Chrome瀏覽器作爲客戶端的Web套接字。 我已將網站的代碼記錄下來。服務器在WebSocket中重新啓動時重新連接客戶端
我運行服務器,客戶端也連接。我也可以聊天。 現在,當我重新啓動服務器(通過將其重新啓動並重新啓動服務器)時, 客戶端將獲取斷開連接的信息,但是當我發送消息時,它自動不會與服務器重新連接。
如何實現這一目標?就像我收到斷開連接的信息一樣,我是否應該檢查並將其發送到JavaScript以刷新頁面或重新連接?
我正在使用使用PHP5和Chrome瀏覽器作爲客戶端的Web套接字。 我已將網站的代碼記錄下來。服務器在WebSocket中重新啓動時重新連接客戶端
我運行服務器,客戶端也連接。我也可以聊天。 現在,當我重新啓動服務器(通過將其重新啓動並重新啓動服務器)時, 客戶端將獲取斷開連接的信息,但是當我發送消息時,它自動不會與服務器重新連接。
如何實現這一目標?就像我收到斷開連接的信息一樣,我是否應該檢查並將其發送到JavaScript以刷新頁面或重新連接?
當服務器重新啓動時,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);
};
}
安德魯給出的解決方案是不完美的工作,因爲在失去連接的情況下,服務器可能會發送多個關閉事件。
在這種情況下,你會設置幾個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 */
/* ... */
}
我一直在用這個有一段時間是純粹的香草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事件發生時未啓動,則該連接在其恢復聯機後仍會恢復。
注意:使用此腳本不會允許您永遠停止嘗試打開連接......但我認爲這就是您想要的?
以下是我在我的項目中使用的代碼,其工作100%。
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(); };
}
GitHub上託管該裝飾的WebSocket的API提供一個WebSocket連接,如果連接中斷,將自動重新連接一個小型的JavaScript庫。
使用gzip壓縮的縮小庫小於600字節。
官方資料庫,請訪問:
https://github.com/joewalnes/reconnecting-websocket
如果當它重新啓動大量的客戶端連接到服務器。 通過使用指數退避算法來管理客戶端的重新連接時間可能是值得的。
該算法是這樣的:
參考:
http://blog.johnryding.com/post/78544969349/how-to-reconnect-web-sockets-in-a-realtime-web-app
ReconnectingWebSocket不處理利用該算法重新連接。
https://github.com/gamestdio/websocket.js使用指數退避 – vgoklani 2016-05-19 11:43:42
很好的答案,尤其是因爲它提到服務器關閉Web套接字連接後服務器負載過高的風險,並且所有客戶端(可能是數百或成千上萬)嘗試同時重新連接。除了指數退避之外,您還可以隨機化0到10秒之間的延遲。這也會將負載分散到服務器上。 – 2017-03-17 15:03:35
不能發表評論,但以下幾點:
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);
我有同樣的問題和解決方案的工作非常出色。感謝名單! – 2011-12-01 13:50:00
你應該在這裏使用一個匿名函數:'function(){start(websocketServerLocation)}'而不是一個字符串,所以你不會觸發'eval()' – 2012-06-22 20:15:08
我希望有更優雅的方式,而不需要構造一個新的對象並定義事件動作... – ciembor 2013-02-10 23:05:27