Ponowne połączenie klienta po ponownym uruchomieniu serwera w WebSocket

Używam web socket używając PHP5 i przeglądarki Chrome jako klienta. Wziąłem Kod ze strony http://code.google.com/p/phpwebsocket/.

Uruchamiam serwer i klient jest również podłączony. Ja też mogę pogadać. Teraz po ponownym uruchomieniu serwera (zabijając go i uruchamiając ponownie), klient pobiera informacje o rozłączeniu, ale automatycznie nie łączy się ponownie z serwerem, gdy wysyłam wiadomość.

Jak to osiągnąć? Jak wtedy, gdy dostaję dis-connected informacje, Czy powinienem to sprawdzić i wysłać do JavaScript, aby odświeżyć stronę lub ponownie połączyć?

 65
Author: siddhusingh, 2010-09-23

6 answers

Po ponownym uruchomieniu serwera połączenie z gniazdem sieciowym jest zamknięte, więc wywołane jest Zdarzenie JavaScript onclose. Oto przykład, który próbuje nawiązać połączenie co pięć sekund.

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);
    };
}
 109
Author: Andrew,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-06 21:30:08

Rozwiązanie podane przez Andrew nie działa idealnie, ponieważ w przypadku utraty połączenia serwer może wysłać kilka bliskich zdarzeń.

W takim przypadku ustawisz kilka settimoutów. rozwiązanie podane przez Andrew może działać tylko wtedy, gdy serwer będzie gotowy przed pięcioma sekundami.

Następnie, w oparciu o rozwiązanie Andrew, przerobiłem, użyłem setInterval dołączając ID do obiektu window (w ten sposób jest dostępny "wszędzie"):

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 */
 /* ... */
}
 33
Author: user2909737,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-06 21:31:14

ReconnectingWebSocket

GitHub posiada małą bibliotekę JavaScript, która dekoruje API WebSocket, aby zapewnić połączenie WebSocket, które automatycznie połączy się ponownie, jeśli połączenie zostanie przerwane.

Minified library with gzip compression is less than 600 bajts.

Oficjalne repozytorium jest dostępne tutaj:

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

Zalanie serwera

Jeśli duża liczba klientów jest podłączona do serwer po ponownym uruchomieniu. Może warto zarządzać czasem ponownego połączenia klientów za pomocą wykładniczego algorytmu cofania.

Algorytm działa tak:

  1. dla prób k, Wygeneruj losowy przedział czasu od 0 do 2^k-1,
  2. jeśli jesteś w stanie ponownie połączyć, zresetuj k do 1,
  3. Jeśli ponowne połączenie nie powiedzie się, K zwiększa się o 1 i proces uruchamia się ponownie w kroku 1,
  4. do skrócenia maksymalnego interwału, gdy pewna liczba prób K ma został osiągnięty, K przestaje wzrastać po każdej próbie.

Référence:

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

ReconnectingWebSocket nie obsługuje ponownego połączenia za pomocą tego algorytmu.

 25
Author: Joël Esponde,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-04 21:31:39

Używam tego patten przez jakiś czas dla pure vanilla JavaScript, i obsługuje kilka więcej przypadków niż inne odpowiedzi.

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);


});

Spróbuje ponownie, gdy tylko serwer zamknie połączenie, i sprawdzi połączenie, aby upewnić się, że działa co 5 sekund.

Więc jeśli serwer nie działa, gdy to działa lub w czasie zdarzenia onclose, połączenie wróci po ponownym uruchomieniu.

Uwaga: użycie tego skryptu nie pozwoli aby kiedykolwiek przestać próbować otworzyć połączenie... ale myślę, że tego właśnie chcesz?

 22
Author: complistic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-06 21:33:12

Poniżej znajdują się kody, których użyłem w moim projekcie, który działa w 100%.

  1. Umieść cały kod websocket wewnątrz funkcji init.
  2. wewnątrz onclose callback ponownie wywołują init.
  3. na koniec wywołujemy funkcję init wewnątrz funkcji document ready.

Var name = sessionStorage.getItem ('Nazwa');

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();   };  
}
 3
Author: Pradeepta,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-03 06:26:18

Nie mogę skomentować, ale:

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);

Plus https://www.npmjs.com/package/back jest już wystarczająco dobry:)

 0
Author: xemasiv,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-14 22:29:27