Переподключение клиента при перезагрузке сервера в WebSocket

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

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

Как достичь этого? Например, когда я получаю несвязанную информацию, должен ли я ее проверить и отправить на JavaScript для обновления страницы или повторного подключения?

Ответ 1

Когда сервер перезагружается, соединение с веб-сокетом закрывается, поэтому запускается событие 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

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

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

Затем, на основе решения Andrew, переработанного, я использовал 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 */
 /* ... */
}

Ответ 3

ReconnectingWebSocket

В GitHub размещена небольшая библиотека JavaScript, которая украшает API WebSocket, чтобы обеспечить соединение WebSocket, которое будет автоматически подключаться, если соединение будет удалено.

Мини-библиотека с сжатием gzip меньше 600 байт.

Официальный репозиторий доступен здесь:

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

Наводнение сервера

Если при перезагрузке подключено большое количество клиентов к серверу. Возможно, целесообразно управлять настройками повторного подключения клиентов с помощью алгоритма экспоненциального отказа.

Алгоритм работает следующим образом:

  • Для k попыток создайте случайный интервал времени между 0 и 2 ^ k - 1,
  • Если вы можете повторно подключиться, reset k к 1,
  • Если повторное соединение не выполняется, k увеличивается на 1, и процесс перезапускается на шаге 1,
  • Чтобы урезать максимальный интервал, когда достигнуто определенное количество попыток k, k прекращает увеличиваться после каждой попытки.

Справочно:

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

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

Ответ 4

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

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

Ответ 5

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

  • Поместите весь код websocket внутри функции init.
  • Внутри обратного вызова onclose снова вызовите init.
  • Наконец, вызовите функцию 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();   };  
}

Ответ 6

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

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