2010-09-23 313 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已经足够好:)

相关问题