143 votes

Fermer correctement WebSocket (HTML5, Javascript)

Je m'amuse avec les WebSockets HTML5. Je me demandais, comment fermer la connexion de manière élégante ? Par exemple, que se passe-t-il si l'utilisateur rafraîchit la page ou ferme simplement le navigateur ?

Il y a un comportement étrange lorsqu'un utilisateur rafraîchit simplement la page sans appeler websocket.close() - lorsqu'ils reviendront après le rafraîchissement, il frappera le websocket.onclose événement.

129voto

kanaka Points 23143

Selon le spécification du protocole v76 (qui est la version que les navigateurs avec le support actuel implémentent) :

Pour fermer la connexion proprement, une trame consistant en un simple octet 0xFF suivi d'un octet 0x00 est envoyée par un pair pour demander que l'autre pair de fermer la connexion.

Si vous écrivez un serveur, vous devez vous assurer d'envoyer une trame de fermeture lorsque le serveur ferme une connexion client. La méthode normale de fermeture des sockets TCP peut parfois être lente et amener les applications à penser que la connexion est toujours ouverte alors qu'elle ne l'est pas.

Le navigateur devrait vraiment le faire pour vous lorsque vous fermez ou rechargez la page. Cependant, vous pouvez vous assurer qu'un cadre de fermeture est envoyé en capturant l'événement beforeunload :

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

Je ne vois pas comment vous pouvez obtenir un événement onclose après le rafraîchissement de la page. L'objet websocket (avec le gestionnaire onclose) n'existera plus lorsque la page sera rechargée. Si vous essayez d'établir une connexion WebSocket sur votre page dès son chargement, il se peut que le serveur refuse une nouvelle connexion si tôt après la déconnexion de l'ancienne (ou que le navigateur ne soit pas prêt à établir des connexions au moment où vous essayez de vous connecter) et que vous obteniez un événement onclose pour le nouvel objet websocket.

2 votes

Il est possible que dans Firefox, la connexion semble se prolonger jusqu'au chargement de la page suivante. Je ne trouve pas de référence mais je pense qu'il y a peut-être eu un bogue à ce sujet. L'autre possibilité est que le onclose est déclenché de manière inattendue, ou peut-être intentionnelle, lorsque l'utilisateur navigue ou que la page est rechargée. J'ai a posté une question demandant quel devrait être le comportement attendu, quel navigateur est le bon et comment mettre en œuvre l'auto-reconnexion.

5 votes

Envisager ces problèmes con onbeforeunload événement

38voto

theoobe Points 131

Le fait est qu'il existe deux versions principales du protocole WebSockets utilisées aujourd'hui. L'ancienne version qui utilise le [0x00][message][0xFF] et puis il y a la nouvelle version qui utilise le protocole Paquets au format Hybi .

L'ancienne version du protocole est utilisée par Opera et les iPod/iPad/iPhones. Il est donc important que la rétrocompatibilité soit mise en œuvre dans les serveurs WebSockets. Avec ces navigateurs qui utilisent l'ancien protocole, j'ai découvert que le fait de rafraîchir la page, de naviguer hors de la page ou de fermer le navigateur entraîne la fermeture automatique de la connexion par le navigateur. Génial !

Cependant, avec les navigateurs utilisant la nouvelle version du protocole (par exemple Firefox, Chrome et éventuellement IE10), il suffit de fermer le navigateur pour que celui-ci ferme automatiquement la connexion. En d'autres termes, si vous actualisez la page ou si vous vous éloignez de la page, le navigateur ne ferme PAS automatiquement la connexion. Cependant, le navigateur envoie au serveur un paquet hybi dont le premier octet (l'identifiant du proto) est le suivant 0x88 (mieux connu sous le nom de cadre de données fermé). Lorsque le serveur reçoit ce paquet, il peut lui-même fermer la connexion de force, si vous le souhaitez.

4 votes

Un exemple pratique côté serveur comment gérer ce paquet hybi ?

11 votes

Il semble insensé qu'il ne ferme pas la connexion. La variable WebSocket est effacée lors du rechargement de la page, alors pourquoi la connexion resterait-elle ouverte si elle n'est pas accessible ? Réutiliser la connexion n'aurait pas de sens non plus.

0 votes

@albanx vérifiez ma réponse ci-dessous

36voto

karlcow Points 4291

Très simple, vous le fermez :)

var myWebSocket = new WebSocket("ws://example.org"); 
myWebSocket.send("Hello Web Sockets!"); 
myWebSocket.close();

Avez-vous vérifié également le site suivant Et vérifiez le article de présentation de l'Opéra

4voto

Artjom Points 889

Comme mentionné par theoobe Certains navigateurs ne ferment pas automatiquement les websockets. N'essayez pas de gérer les événements "fermer la fenêtre du navigateur" côté client. Il n'existe actuellement aucun moyen fiable de le faire, si l'on considère la prise en charge des principaux navigateurs de bureau. ET les navigateurs mobiles (par exemple onbeforeunload ne fonctionnera pas dans Mobile Safari). J'ai une bonne expérience de la gestion de ce problème côté serveur. Par exemple, si vous utilisez Java EE, jetez un coup d'oeil à javax.websocket.Endpoint Selon le navigateur, l'une ou l'autre des options suivantes est disponible OnClose ou la méthode OnError sera appelée si vous fermez/rechargez la fenêtre du navigateur.

4voto

rong liu Points 1

Veuillez utiliser ce

var uri = "ws://localhost:5000/ws";
var socket = new WebSocket(uri);
socket.onclose = function (e){
    console.log(connection closed);
};
window.addEventListener("unload", function () {
    if(socket.readyState == WebSocket.OPEN)
        socket.close();
});

La fermeture du navigateur ne déclenche pas l'événement de fermeture de la websocket. Vous devez appeler socket.close() manuellement.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X