代码之家  ›  专栏  ›  技术社区  ›  siddhusingh

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

  •  77
  • siddhusingh  · 技术社区  · 14 年前

    我从网站上取了密码 http://code.google.com/p/phpwebsocket/ .

    现在,当我重新启动服务器时(通过杀死它并再次启动它) 客户端获取断开连接的信息,但在我发送消息时自动不与服务器重新连接。

    如何做到这一点?比如当我得到断开连接的信息时,我应该检查它并将其发送到JavaScript以刷新页面还是重新连接?

    6 回复  |  直到 5 年前
        1
  •  144
  •   Peter Mortensen mkoryak    7 年前

    当服务器重新启动时,Web套接字连接关闭,因此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);
        };
    }
    
        2
  •  42
  •   Peter Mortensen mkoryak    7 年前

    Andrew给出的解决方案并不完美,因为在失去连接的情况下,服务器可能会发送几个关闭事件。

    然后,基于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 */
     /* ... */
    }
    
        3
  •  39
  •   Joël Esponde    4 年前

    有一个小的JavaScript库修饰websocketapi,以提供一个WebSocket连接,如果连接断开,该连接将自动重新连接。

    gzip压缩的小型库小于600字节。

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

    还有一个TypeScript库。包括它并替换它 new WebSocket 具有 new ReconnectingWebSocket .

    https://github.com/pladaria/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不会使用此算法处理重新连接。

        4
  •  29
  •   Peter Mortensen mkoryak    7 年前

    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
  •  2
  •   Pradeepta    7 年前

    下面是我在我的项目中使用的代码,工作100%。

    1. 最后在documentready函数中调用init函数。

    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();   };  
    }
    
        6
  •  2
  •   xemasiv    7 年前

    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 已经足够好了:)

        7
  •  1
  •   Zibri    4 年前

    function wsConnection(url){
        var ws = new WebSocket(url);
        var s = (l)=>console.log(l);
    	ws.onopen = m=>s(" CONNECTED")
        ws.onmessage = m=>s(" RECEIVED: "+JSON.parse(m.data))
        ws.onerror = e=>s(" ERROR")
        ws.onclose = e=>{
            s(" CONNECTION CLOSED");
            setTimeout((function() {
                var ws2 = new WebSocket(ws.url);
    			ws2.onopen=ws.onopen;
                ws2.onmessage = ws.onmessage;
                ws2.onclose = ws.onclose;
                ws2.onerror = ws.onerror;
                ws = ws2
            }
            ).bind(this), 5000)
        }
        var f = m=>ws.send(JSON.stringify(m)) || "Sent: "+m;
        f.ping = ()=>ws.send(JSON.stringify("ping"));
        f.close = ()=>ws.close();
        return f
    }
    
    c=new wsConnection('wss://echo.websocket.org');
    setTimeout(()=>c("Hello world...orld...orld..orld...d"),5000);
    setTimeout(()=>c.close(),10000);
    setTimeout(()=>c("I am still alive!"),20000);
    <pre>
    This code will create a websocket which will 
    reconnect automatically after 5 seconds from disconnection.
    
    An automatic disconnection is simulated after 10 seconds.
        8
  •  0
  •   Waket Zheng    4 年前

    最后,在vue+ts中实现ws-auto-reconnect,如下所示:

    private async mounted() {
        // Connect to WebSocket
        const sn = "sb1234567890";
        const host =
            window.location.protocol == "https:"
                ? "wss://www.xxx.net"
                : process.env.DEV_TYPE === "fullstack"
                ? "ws://10.0.0.14:8528"
                : "ws://www.xxx.net:8528";
        const wsUri = host + "/feed-home/" + sn;
        await this.startWs(wsUri, sn);
        // !!!Deprecated: failed to reconnect
        // let ws = new WebSocket();
        // console.log(ws);
        // ws.onopen = async function(event) {
        //     console.log(event, "openEvent");
        //     clearInterval(that.timer);
        // };
        // ws.onclose = async function(event) {
        //     console.log(event, "close");
        //     that.timer = setInterval(() => {
        //         console.log("Heart Beat");
        //         ws.send("HeartBeat");
        //         // ws = new WebSocket("ws://10.0.0.14:8528/feed-home/" + sn);
        //         console.log(ws);
        //     }, 60000);
        // };
        // ws.onmessage = async function(event) {
        //     console.log(event, "ws");
        //     alert("get it!");
        //     await alert("please update!");
        //     await that.getHome(sn);
        // };
    }
    private wsReconnected: boolean = false; // check whether WebSocket is reconnected
    private async startWs(uri: string, sn: string) {
        let that = this;
        let ws = new WebSocket(uri);
        ws.onopen = async () => {
            if (that.wsReconnected) {
                await that.getHome(sn); // Refresh api data after reconnected
            }
            ws.send("Current client version: " + window.version);
        };
        ws.onmessage = async evt => {
            await that.getHome(sn);
            that.$message({
                type: "success",
                message: evt.data,
                showClose: true,
                center: true,
                duration: 20 * 1000
            });
        };
        ws.onclose = async () => {
            that.wsReconnected = true;
            await that.startWs(uri, sn);
            const sleep = (seconds: number) => {
                return new Promise(resolve =>
                    setTimeout(resolve, seconds * 1000)
                );
            };
            await sleep(10); // Try to reconnect in 10 seconds
            // !!!Deprecated: Use timer will cause multiply ws connections
            // if (!that.wsTimer) {
            //     // Try to reconnect in 10 seconds
            //     that.wsTimer = setInterval(async () => {
            //         console.log("reconnecting websocket...");
            //         await that.startWs(uri, sn);
            //     }, 10 * 1000);
            // }
        };
    }
    
        9
  •  0
  •   leoncc    4 年前

    很干净 财产,对我很有用。在客户端计算机进入睡眠模式等情况下,或者服务器意外停止等情况下,它似乎被设置为true。如果手动关闭套接字,它将被设置为false,在这种情况下,您不希望再次自动打开套接字。下面是Angular 7项目的代码。我在一个服务中有这个代码,所以它可以从任何组件中使用。

        notifySocketClose(event) { 
    
            if (!event.wasClean) { 
                setTimeout(() => {
                    this.setupSocket()
                }, 1000);       
            }
        }
    
        setupSocket() { // my function to handle opening of socket, event binding etc.
        .....
        .....
    
                this.websocketConnection = this.websocketConnection ? this.websocketConnection : new WebSocket(socketUrl);
                this.websocketConnection.onclose = this.notifySocketClose.bind(this);   
            } 
        }
        .....
        .....