2011-01-27 40 views
93

Estoy jugando con HTML5 WebSockets. Me preguntaba, ¿cómo puedo cerrar la conexión con gracia? ¿Qué ocurre si el usuario actualiza la página o simplemente cierra el navegador?Cerrando WebSocket correctamente (HTML5, Javascript)

Hay un comportamiento extraño cuando un usuario simplemente actualiza la página sin llamar al websocket.close() - cuando regresan después de la actualización, se activará el evento websocket.onclose.

Respuesta

70

De acuerdo con la protocol spec v76 (que es la versión que navegador con soporte actual implementar) :

Para cerrar la conexión de forma limpia, un marco que consiste en solo un byte 0x35 0xFF seguido de un byte 0x00 se envía desde un par para solicitar que el otro par cierre la conexión.

Si está escribiendo un servidor, debe asegurarse de enviar un marco cerrado cuando el servidor cierre una conexión de cliente. El método de cierre de socket TCP normal a veces puede ser lento y hacer que las aplicaciones piensen que la conexión aún está abierta, incluso cuando no lo está.

El navegador realmente debería hacer esto cuando cierra o recarga la página. Sin embargo, puede asegurarse un marco de estrecha se envía al hacer la captura del evento beforeunload:

window.onbeforeunload = function() { 
    websocket.onclose = function() {}; // disable onclose handler first 
    websocket.close() 
}; 

No estoy seguro de cómo puede estar recibiendo un evento OnClose después de que la página se actualiza. El objeto websocket (con el manejador onclose) ya no existirá una vez que la página se vuelva a cargar. Si intenta establecer de inmediato una conexión WebSocket en su página a medida que se carga la página, es posible que se encuentre con un problema donde el servidor rechaza una nueva conexión tan pronto después de que la anterior se desconectó (o el navegador no está listo) para hacer conexiones en el punto en el que intentas conectarte) y obtienes un evento onclose para el nuevo objeto websocket.

+1

Es posible que en Firefox la conexión parezca estar en la carga de la página siguiente. No puedo encontrar una referencia, pero creo que puede haber un error al respecto. La otra posibilidad es que el evento 'onclose' se active inesperadamente, o tal vez a propósito, a medida que el usuario navega/página se vuelve a cargar. He [publicado una pregunta] (http://stackoverflow.com/questions/10965720/should-websocket-onclose-be-triggered-by-user-navigation-or-refresh) preguntando cuál debería ser el comportamiento esperado, que navegador tiene razón y cómo implementamos la reconexión automática. – leggetter

+3

considere [estos problemas] (http://stackoverflow.com/questions/14645011/window-onbeforeunload-and-window-onunload-is-not-working-in-firefox-safari-o) con el evento 'onbeforeunload' – artkoenig

31

Lo que pasa es que hay dos versiones principales de protocolo de WebSockets en uso en la actualidad. La versión anterior que usa el protocolo [0x00][message][0xFF], y luego está la nueva versión que usa Hybi con formato de paquetes.

La versión de protocolo anterior es utilizada por Opera y iPod/iPad/iPhones por lo que es realmente importante que la compatibilidad con versiones anteriores se implemente en los servidores de WebSockets. Con estos navegadores utilizando el protocolo anterior, descubrí que al actualizar la página, o al navegar fuera de la página, o al cerrar el navegador, todo da como resultado que el navegador cierre automáticamente la conexión. ¡¡Estupendo!!

Sin embargo, con los navegadores que usan la nueva versión de protocolo (por ejemplo, Firefox, Chrome y finalmente IE10), solo cerrar el navegador hará que el navegador cierre automáticamente la conexión. Es decir, si actualiza la página o navega fuera de la página, el navegador NO cierra automáticamente la conexión. Sin embargo, lo que hace el navegador es enviar un paquete hybi al servidor con el primer byte (el identificador de proto) como 0x88 (mejor conocido como el marco de datos cerrado). Una vez que el servidor recibe este paquete, puede cerrar forzosamente la conexión, si así lo desea.

+3

a ejemplo práctico en el lado del servidor de cómo administrar este paquete hybi? – albanx

+7

Parece una locura que no cierre la conexión. La variable WebSocket se elimina en la recarga de página, entonces ¿por qué la conexión permanecerá abierta si no se puede acceder? Reutilizar la conexión tampoco tendría sentido. – Triynko

+0

@albanx compruebe mi respuesta a continuación – artkoenig

2

Según lo mencionado por theoobe, algunos navegadores no cierran los websockets de forma automática. No intente manejar ningún evento de "cerrar la ventana del navegador" del lado del cliente. Actualmente no hay una manera confiable de hacerlo, si considera que la compatibilidad con los principales navegadores móviles de escritorio y (por ejemplo, onbeforeunload no funcionará en Mobile Safari). Tuve una buena experiencia en el manejo de este problema del lado del servidor. P.ej. si utiliza Java EE, consulte javax.websocket.Endpoint, dependiendo del navegador, se llamará al método OnClose o al método OnError si cierra/recarga la ventana del navegador.

+1

En mi caso, la conexión se cierra durante la transferencia de datos, funciona bien en el caso de navegadores de la familia Opera y iOS. Por favor, ayúdenme. Estoy luchando con este problema desde hace dos semanas. http://stackoverflow.com/q/30799814/2225439 – Mrug