Переподключение клиента при перезагрузке сервера в WebSocket
Я использую веб-сокет, используя PHP5 и браузер Chrome в качестве клиента. Я взял код с сайта http://code.google.com/p/phpwebsocket/.
Я запускаю сервер, и клиент также подключен. Я тоже могу поболтать. Теперь, когда я перезапускаю сервер (убив его и запустив его снова), клиент получает отключенную информацию, но автоматически не подключается к серверу при отправке сообщения.
Как этого добиться? Например, когда я получите информацию о Dis-connected, должен ли я проверить ее и отправить в JavaScript для обновления страницы или повторного подключения?
6 ответов:
когда сервер перезагружается, соединение с веб-сокетом закрывается, поэтому 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); }; }
решение, данное Андреем, не работает идеально, потому что в случае потери соединения сервер может отправить несколько близких событий.
в этом случае вы установите несколько 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 */ /* ... */ }
ReconnectingWebSocket
в GitHub размещена небольшая библиотека JavaScript, которая украшает API WebSocket, чтобы обеспечить подключение WebSocket, которое будет автоматически повторно подключаться, если соединение будет удалено.
уменьшенная библиотека с сжатием gzip составляет менее 600 байт.
официальный репозиторий доступен здесь:
https://github.com/joewalnes/reconnecting-websocket
сервер потока
Если a при перезагрузке к серверу подключается большое количество клиентов. Возможно, стоит управлять таймингами повторного подключения клиентов с помощью экспоненциального алгоритма обратного отсчета.
алгоритм работает следующим образом:
- для K попыток сгенерируйте случайный интервал времени между 0 и 2^k-1,
- если вы можете снова подключиться, сбросьте k до 1,
- если повторное подключение не удается, k увеличивается на 1 и процесс перезапускается на шаге 1,
- для усечения максимального интервала, когда достигнуто определенное количество попыток k, k перестает увеличиваться после каждой попытки.
Référence:
http://blog.johnryding.com/post/78544969349/how-to-reconnect-web-sockets-in-a-realtime-web-app
ReconnectingWebSocket не обрабатывает повторные подключения с помощью этого алгоритма.
Я использую этот Паттен некоторое время для чистого ванильного 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 соединение все равно вернется, как только оно вернется в сеть.
Примечание: используя это скрипт не позволит вам когда-либо прекратить попытки открыть соединение... но я думаю, что это то, что вы хотите?
Ниже приведены коды, которые я использовал в своем проекте, который работает на 100%.
- поместите весь код websocket внутри функции init.
- внутри метод onclose обратного вызова, повторный вызов метода init.
- наконец, вызовите функцию init внутри функции готовности документа.
var name = sessionStorage.getItem ('имя');
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(); }; }
Не могу комментировать, но следующее:
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 уже достаточно хорошо:)