服务器在WebSocket中重新启动时重新连接客户端

sid*_*ngh 85 websocket

我使用PHP5和Chrome浏览器作为客户端使用Web套接字.我从网站http://code.google.com/p/phpwebsocket/上获取了代码.

我运行服务器,客户端也连接.我也可以聊天.现在,当我重新启动服务器(通过杀死它并再次启动它)时,客户端获取断开连接的信息,但在发送消息时自动不会重新连接服务器.

怎么做到这一点?就像我收到断开连接的信息一样,我应该检查它并将其发送到JavaScript以刷新页面或重新连接吗?

And*_*rew 135

当服务器重新启动时,Web Socket连接将关闭,因此onclose会触发JavaScript 事件.这是一个尝试每五秒重新连接的示例.

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);
    };
}
Run Code Online (Sandbox Code Playgroud)

  • 你应该添加"ws = null;" 在setTimeout()之前避免乘以ws对象和eventHandligs (12认同)
  • 如果我错了,请纠正我,但是这段代码有点危险,因为一定量的断开会导致堆栈溢出.那是因为你递归地调用`start`而不返回. (7认同)
  • @Forivin这里没有stackoverflow问题.由于Javascript中只有1个单线程在任何给定时刻执行我们的代码,因此setTimeout()会调度将来执行的函数,当该单个线程再次空闲时.在这里调用setTimeout()之后,线程从函数返回(清除堆栈),然后继续处理队列中的下一个事件.它最终将转到我们的匿名函数,该函数调用start并将其作为堆栈中的顶部框架调用. (6认同)
  • 我希望有更优雅的方式,无需构建新对象和定义事件动作...... (3认同)
  • 5分钟后,浏览器冻结.我是唯一一个? (2认同)
  • 每当当前连接终止时,都会调用@VinayPrabhakaran`onclose`,包括从`onclose`处理程序内部创建的连接。因此,使用setInterval会过多。 (2认同)
  • 通过在设置另一个之前使用 `global_timer_id` 和 `clearTimeout(global_timer_id)`,避免运行多个超时实例。 (2认同)

use*_*737 38

安德鲁给出的解决方案并不完美,因为如果连接丢失,服务器可能会发送几个关闭事件.

在这种情况下,您将设置几个setTimout.安德鲁给出的解决方案可能仅在服务器在五秒钟之前就绪时才有效.

然后,基于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 */
 /* ... */
}
Run Code Online (Sandbox Code Playgroud)

  • “安德鲁给出的解决方案可能只有在服务器在五秒之前准备就绪的情况下才有效。”——这种说法不正确。如果五秒后服务器仍然不可用,您的客户端将无法打开 WebSocket 连接,并且将再次触发“onclose”事件。 (3认同)

Joë*_*nde 31

ReconnectingWebSocket

GitHub托管一个小的JavaScript库,它装饰WebSocket API以提供WebSocket连接,如果连接断开,它将自动重新连接.

使用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

重新连接WebSocket不会使用此算法处理重新连接.


com*_*tic 28

我一直在使用这个patten一段时间用于纯粹的vanilla 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);


});
Run Code Online (Sandbox Code Playgroud)

一旦服务器关闭连接,这将重试,它将检查连接以确保它每5秒钟也会启动.

因此,如果服务器在运行时或在onclose事件发生时未启动,则一旦重新联机,连接仍将返回.

注意:使用此脚本将不允许您停止尝试打开连接...但我认为这是您想要的?

  • 我只会改变:function check(){if(!ws || ws.readyState === WebSocket.CLOSED)start(); } (7认同)