que - Reconexión de Cliente cuando el servidor se reinicia en WebSocket
websockets java (6)
Estoy usando un socket web usando PHP5 y el navegador Chrome como cliente. Tomé el código del sitio http://code.google.com/p/phpwebsocket/ .
Ejecuto el servidor y el cliente también está conectado. Yo también puedo chatear Ahora cuando reinicio el servidor (eliminándolo e iniciándolo de nuevo), el cliente obtiene la información desconectada, pero automáticamente no se vuelve a conectar con el servidor cuando envío el mensaje.
¿Cómo lograr esto? Al igual que cuando obtengo la información desconectada, ¿debo revisarla y enviarla a JavaScript para actualizar la página o volver a conectar?
ReconectandoWebSocket
GitHub alberga una pequeña biblioteca de JavaScript que decora la API de WebSocket para proporcionar una conexión WebSocket que se volverá a conectar automáticamente si se corta la conexión.
La biblioteca reducida con compresión gzip tiene menos de 600 bytes.
El repositorio oficial está disponible aquí:
https://github.com/joewalnes/reconnecting-websocket
Inundación del servidor
Si hay una gran cantidad de clientes conectados al servidor cuando se reinicia. Puede valer la pena administrar los tiempos de reconexión de los clientes mediante el uso de un algoritmo de retroceso exponencial.
El algoritmo funciona así:
- Para k intentos, genere un intervalo de tiempo aleatorio entre 0 y 2 ^ k - 1,
- Si puede volver a conectarse, restablezca k a 1,
- Si la reconexión falla, k aumenta en 1 y el proceso se reinicia en el paso 1,
- Para truncar el intervalo máximo, cuando se ha alcanzado un cierto número de intentos k, k deja de aumentar después de cada intento.
Referencia:
http://blog.johnryding.com/post/78544969349/how-to-reconnect-web-sockets-in-a-realtime-web-app
ReconnectingWebSocket no maneja reconexiones utilizando este algoritmo.
A continuación están los códigos que he usado en mi proyecto que funcionan al 100%.
- Pon todo el código websocket dentro de la función init.
- Dentro de la devolución de llamada onclose llame de nuevo a init.
- Finalmente, llame a la función init dentro de la función de documento preparado.
var name = sessionStorage.getItem (''nombre'');
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(); };
}
He estado usando este patten por un tiempo para JavaScript puro y vainilla, y admite algunos casos más que las otras respuestas.
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);
});
Esto volverá a intentarse tan pronto como el servidor cierre la conexión, y comprobará la conexión para asegurarse de que también esté activa cada 5 segundos.
Por lo tanto, si el servidor no está funcionando cuando se ejecuta o en el momento del evento onclose, la conexión seguirá apareciendo una vez que vuelva a estar en línea.
NOTA: El uso de este script no le permitirá dejar de intentar abrir una conexión ... ¿pero creo que eso es lo que quiere?
La solución dada por Andrew no funciona perfectamente porque, en caso de pérdida de conexión, el servidor podría enviar varios eventos cercanos.
En ese caso, configurará varios setTimout. La solución dada por Andrew solo puede funcionar si el servidor está listo antes de cinco segundos.
Luego, en base a la solución de Andrew, modificada, utilicé setInterval adjuntando la identificación al objeto de la ventana (de esa manera está disponible "en todas partes"):
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 */
/* ... */
}
No puedo comentar, pero lo siguiente:
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);
Además, https://www.npmjs.com/package/back ya es lo suficientemente bueno :)
Cuando el servidor se reinicia, la conexión Web Socket se cierra, por lo que se onclose
evento JavaScript onclose
. Aquí hay un ejemplo que intenta volver a conectar cada cinco segundos.
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);
};
}