web-dev-qa-db-fra.com

Reconnexion du client lorsque le serveur redémarre dans WebSocket

J'utilise une socket Web avec PHP5 et le Chrome en tant que client. J'ai pris le code du site http://code.google.com/p/phpwebsocket/ .

Je lance le serveur et le client est également connecté. Je peux discuter aussi. Maintenant, lorsque je redémarre le serveur (en le tuant et en le redémarrant), le client obtient les informations déconnectées, mais ne se reconnecte pas automatiquement avec le serveur lorsque j'envoie le message.

Comment y parvenir? Comme lorsque je reçois les informations déconnectées, dois-je les vérifier et les envoyer à JavaScript pour actualiser la page ou se reconnecter?

85
siddhusingh

Lorsque le serveur redémarre, la connexion Web Socket est fermée. L'événement JavaScript onclose est donc déclenché. Voici un exemple qui tente de se reconnecter toutes les cinq secondes.

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);
    };
}
133
Andrew

La solution proposée par Andrew ne fonctionne pas parfaitement car, en cas de perte de connexion, le serveur peut envoyer plusieurs événements proches.

Dans ce cas, vous définissez plusieurs setTimout. La solution donnée par Andrew ne peut fonctionner que si le serveur est prêt avant cinq secondes.

Ensuite, basé sur la solution Andrew, retravaillée, j’ai utilisé setInterval pour attacher l’ID à l’objet window (ainsi, il est disponible "partout"):

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 */
 /* ... */
}
38
user2909737

Reconnecter WebSocket

GitHub héberge une petite bibliothèque JavaScript qui décore l'API WebSocket pour fournir une connexion WebSocket qui se reconnectera automatiquement si la connexion est interrompue.

La bibliothèque réduite avec compression gzip est inférieure à 600 octets.

Le référentiel officiel est disponible ici:

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

Inondation de serveur

Si un nombre élevé de clients sont connectés au serveur lors de son redémarrage. Il peut être intéressant de gérer les timings de reconnexion des clients en utilisant un algorithme de suppression exponentielle.

L'algorithme fonctionne comme ceci:

  1. Pour k tentatives, générez un intervalle de temps aléatoire entre 0 et 2 ^ k - 1,
  2. Si vous pouvez vous reconnecter, remettez k à 1,
  3. Si la reconnexion échoue, k augmente de 1 et le processus redémarre à l’étape 1.
  4. Pour tronquer l'intervalle maximal, lorsqu'un certain nombre de tentatives a été atteint, k cesse d'augmenter après chaque tentative.

Référence:

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

ReconnectingWebSocket ne gère pas les reconnexions à l'aide de cet algorithme.

31
Joël Esponde

Cela fait un moment que je me sers de ce modèle pour du code JavaScript pur à la vanille, et il prend en charge un peu plus de cas que les autres réponses.

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


});

Ceci réessayera dès que le serveur fermera la connexion et vérifiera la connexion pour s'assurer qu'elle est aussi active toutes les 5 secondes.

Donc, si le serveur n’est pas actif lors de l’exécution ou au moment de l’événement onclose, la connexion sera rétablie une fois qu’elle est revenue en ligne.

NOTE: L'utilisation de ce script ne vous permettra pas d'arrêter d'essayer d'ouvrir une connexion ... mais je pense que c'est ce que vous voulez?

26
complistic

Vous trouverez ci-dessous les codes que j'ai utilisés dans mon projet et qui fonctionnent à 100%.

  1. Mettez tout le code websocket dans la fonction init.
  2. Dans le rappel onclose, appelez à nouveau init.
  3. Enfin, appelez la fonction init dans la fonction Document Ready.

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();   };  
}
2
Pradeepta

Je ne peux pas commenter, mais ce qui suit:

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 est déjà assez bon :)

2
xemasiv