Переподключение клиента при перезагрузке сервера в WebSocket - PullRequest
83 голосов
/ 23 сентября 2010

Я использую веб-сокет, используя PHP5 и браузер Chrome в качестве клиента.Я взял код с сайта http://code.google.com/p/phpwebsocket/.

Я запускаю сервер, и клиент также подключен.Я тоже могу общаться.Теперь, когда я перезагружаю сервер (убив его и снова запуская), клиент получает отключенную информацию, но автоматически не соединяется с сервером при отправке сообщения.Например, когда я получаю отключенную информацию, я должен проверить ее и отправить в JavaScript, чтобы обновить страницу или восстановить соединение?

Ответы [ 6 ]

131 голосов
/ 22 ноября 2011

Когда сервер перезагружается, соединение через веб-сокет закрывается, поэтому запускается событие 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);
    };
}
38 голосов
/ 16 декабря 2013

Решение, данное Эндрю, не идеально работает, потому что в случае потери соединения сервер может отправить несколько событий закрытия.

В этом случае вы установите несколько setTimout's. Решение, данное Эндрю, может работать, только если сервер будет готов раньше, чем через пять секунд.

Затем, на основе переработанного решения Эндрю, я использовал setInterval, прикрепляющий идентификатор к объекту окна (таким образом, он доступен «везде»):

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 */
 /* ... */
}
31 голосов
/ 05 мая 2016

ReconnectingWebSocket

GitHub содержит небольшую библиотеку JavaScript, которая украшает API WebSocket, чтобы обеспечить соединение 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

ReconnectingWebSocket не обрабатывает переподключения с использованием этого алгоритма.

26 голосов
/ 13 августа 2015

Я использовал этот шаблон некоторое время для чистого ванильного 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, соединение все равно будет возвращено, как только он снова будет в сети.

ПРИМЕЧАНИЕ. Использование этого скрипта не позволит вам когда-либо прекратить попытки открыть соединение ... но я думаю, что вы этого хотите?

2 голосов
/ 15 декабря 2017

Не могу комментировать, но следующее:

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 уже достаточно хорош:)

2 голосов
/ 19 августа 2015

Ниже приведены коды, которые я использовал в своем проекте, которые работают на 100%.

  1. Поместите весь код веб-сокета в функцию 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();   };  
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...