Fermer correctement WebSocket (HTML5, Javascript)

127

Je joue avec les WebSockets HTML5. Je me demandais, comment puis-je fermer la connexion gracieusement? Par exemple, que se passe-t-il si l'utilisateur actualise la page ou ferme simplement le navigateur?

Il y a un comportement étrange lorsqu'un utilisateur actualise simplement la page sans appeler websocket.close()- quand il revient après l'actualisation, il atteint l' websocket.oncloseévénement.

Andy Hin
la source

Réponses:

111

Selon la spécification de protocole v76 (qui est la version que le navigateur avec le support actuel implémente):

Pour fermer proprement la connexion, une trame constituée simplement d'un octet 0xFF suivi d'un octet 0x00 est envoyée par un pair pour demander que l'autre pair ferme 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 du socket TCP peut parfois être lente et amener les applications à penser que la connexion est toujours ouverte même si ce n'est pas le cas.

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

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

Je ne sais pas comment vous pouvez obtenir un événement onclose après l'actualisation de la page. L'objet websocket (avec le gestionnaire onclose) n'existera plus une fois la page rechargée. Si vous essayez immédiatement d'établir une connexion WebSocket sur votre page pendant le chargement de la page, vous rencontrez peut-être un problème où le serveur refuse une nouvelle connexion si peu de temps après la déconnexion de l'ancienne (ou le navigateur n'est pas prêt pour établir des connexions au moment où vous essayez de vous connecter) et vous obtenez un événement onclose pour le nouvel objet websocket.

Kanaka
la source
2
Il est possible que dans Firefox, la connexion semble traîner dans le prochain chargement de la page. Je ne trouve pas de référence mais je pense qu'il y a peut-être eu un bug à ce sujet. L'autre possibilité est que l' oncloseévénement soit déclenché de manière inattendue, ou peut-être exprès, lorsque l'utilisateur navigue / page est rechargée. J'ai posté une question demandant quel devrait être le comportement attendu, quel navigateur l'a bien et comment nous implémentons la reconnexion automatique.
leggetter
4
considérez ces problèmes avec l' onbeforeunloadévénement
artkoenig
36

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 consultez l' article d'introduction d'Opera

karlcow
la source
35

Le fait est qu'il existe aujourd'hui 2 principales versions de protocole de WebSockets. L'ancienne version qui utilise le [0x00][message][0xFF]protocole, puis il y a la nouvelle version utilisant des paquets formatés Hybi .

L'ancienne version du protocole est utilisée par Opera et iPod / iPad / iPhones, il est donc important que la rétrocompatibilité soit implémentée dans les serveurs WebSockets. Avec ces navigateurs utilisant l'ancien protocole, j'ai découvert que l'actualisation de la page, la navigation en dehors de la page ou la fermeture du navigateur entraînent tous 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), seule la fermeture du navigateur entraînera la fermeture automatique de la connexion par le navigateur. C'est-à-dire que si vous actualisez la page ou si vous quittez la page, le navigateur ne ferme PAS automatiquement la connexion. Cependant, ce que fait le navigateur, c'est envoyer un paquet hybi au serveur avec le premier octet (l'identifiant proto) 0x88(mieux connu sous le nom de trame de données fermée). Une fois que le serveur reçoit ce paquet, il peut fermer de force la connexion elle-même, si vous le souhaitez.

Théoobe
la source
4
un exemple pratique côté serveur comment gérer ce paquet hybi?
albanx le
9
Il semble insensé que cela 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.
Triynko
@albanx vérifiez ma réponse ci
artkoenig
Tous les exemples de code sur la façon d'envoyer une trame de fermeture à partir d'un client Websocket (par exemple, un navigateur). J'utilise le module ws npm
Shaik Syed Ali
3

Comme mentionné par theoobe , certains navigateurs ne ferment pas automatiquement les Websockets. N'essayez pas de gérer les événements de "fermeture de la fenêtre du navigateur" côté client. Il n'existe actuellement aucun moyen fiable de le faire, si vous considérez la prise en charge des principaux navigateurs de bureau ET mobiles (par exemple onbeforeunload, ne fonctionnera pas dans Mobile Safari). J'ai eu une bonne expérience dans la gestion de ce problème côté serveur. Par exemple, si vous utilisez Java EE, jetez un œil à javax.websocket.Endpoint , selon le navigateur, la OnCloseméthode ou la OnErrorméthode sera appelée si vous fermez / rechargez la fenêtre du navigateur.

artkoenig
la source
1
Dans mon cas, la connexion se ferme pendant le transfert de données, cela fonctionne bien dans le cas des navigateurs de la famille Opera et iOS. S'il vous plaît, aidez-moi .. Je me bats avec ce problème depuis deux semaines. stackoverflow.com/q/30799814/2225439
Mrug
2

En utilisant la méthode close de web socket, où vous pouvez écrire n'importe quelle fonction selon les besoins.

var connection = new WebSocket('ws://127.0.0.1:1337');
    connection.onclose = () => {
            console.log('Web Socket Connection Closed');
        };
Akanksha Raizada
la source