WebSocket korrekt schließen (HTML5, Javascript)

127

Ich spiele mit HTML5 WebSockets herum. Ich habe mich gefragt, wie ich die Verbindung ordnungsgemäß schließen kann. Was passiert beispielsweise, wenn der Benutzer die Seite aktualisiert oder nur den Browser schließt?

Es gibt ein seltsames Verhalten, wenn ein Benutzer die Seite nur ohne Aufruf aktualisiert websocket.close()- wenn er nach der Aktualisierung zurückkehrt, wird das websocket.oncloseEreignis getroffen.

Andy Hin
quelle

Antworten:

110

Gemäß der Protokollspezifikation v76 (dies ist die Version, die der Browser mit der aktuellen Unterstützung implementiert):

Um die Verbindung sauber zu schließen, wird von einem Peer ein Frame gesendet, der nur aus einem 0xFF-Byte gefolgt von einem 0x00-Byte besteht, um den anderen Peer zu bitten, die Verbindung zu schließen.

Wenn Sie einen Server schreiben, sollten Sie sicherstellen, dass Sie einen geschlossenen Frame senden, wenn der Server eine Clientverbindung schließt. Die normale Methode zum Schließen von TCP-Sockets kann manchmal langsam sein und dazu führen, dass Anwendungen glauben, die Verbindung sei noch offen, auch wenn dies nicht der Fall ist.

Der Browser sollte dies wirklich für Sie tun, wenn Sie die Seite schließen oder neu laden. Sie können jedoch sicherstellen, dass ein enger Frame gesendet wird, indem Sie das Ereignis beforeunload erfassen:

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

Ich bin nicht sicher, wie Sie ein Onclose-Ereignis erhalten können, nachdem die Seite aktualisiert wurde. Das Websocket-Objekt (mit dem Onclose-Handler) ist nach dem erneuten Laden der Seite nicht mehr vorhanden. Wenn Sie beim Laden der Seite sofort versuchen, eine WebSocket-Verbindung auf Ihrer Seite herzustellen, tritt möglicherweise ein Problem auf, bei dem der Server eine neue Verbindung so bald ablehnt, nachdem die alte getrennt wurde (oder der Browser nicht bereit ist) um Verbindungen an dem Punkt herzustellen, an dem Sie versuchen, eine Verbindung herzustellen) und Sie erhalten ein Onclose-Ereignis für das neue Websocket-Objekt.

Kanaka
quelle
2
Es ist möglich, dass in Firefox die Verbindung beim Laden der nächsten Seite hängen bleibt. Ich kann keine Referenz finden, aber ich denke, dass diesbezüglich ein Fehler aufgetreten ist. Die andere Möglichkeit besteht darin, dass das oncloseEreignis unerwartet oder absichtlich ausgelöst wird, wenn der Benutzer navigiert / die Seite neu geladen wird. Ich habe eine Frage gestellt, in der gefragt wird, wie das erwartete Verhalten aussehen soll, welcher Browser es richtig macht und wie wir die automatische Wiederverbindung implementieren.
Leggetter
4
Betrachten Sie diese Probleme mit onbeforeunloadEreignis
Artkoenig
36

Sehr einfach, du schließt es :)

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

Haben Sie auch die folgende Seite überprüft und den Einführungsartikel von Opera gelesen?

Karlcow
quelle
35

Die Sache ist, dass heute zwei Hauptprotokollversionen von WebSockets verwendet werden. Die alte Version, die das [0x00][message][0xFF]Protokoll verwendet, und dann gibt es die neue Version, die Hybi-formatierte Pakete verwendet .

Die alte Protokollversion wird von Opera und iPod / iPad / iPhones verwendet, daher ist es wichtig, dass die Abwärtskompatibilität auf WebSockets-Servern implementiert ist. Bei diesen Browsern, die das alte Protokoll verwenden, habe ich festgestellt, dass das Aktualisieren der Seite oder das Navigieren von der Seite weg oder das Schließen des Browsers dazu führt, dass der Browser die Verbindung automatisch schließt. Toll!!

Bei Browsern, die die neue Protokollversion verwenden (z. B. Firefox, Chrome und eventuell IE10), führt das Schließen des Browsers dazu, dass der Browser die Verbindung automatisch schließt. Das heißt, wenn Sie die Seite aktualisieren oder von der Seite weg navigieren, schließt der Browser die Verbindung NICHT automatisch. Der Browser sendet jedoch ein Hybi-Paket an den Server, wobei das erste Byte (die Proto-Identität) 0x88(besser bekannt als "Close Data Frame") verwendet wird. Sobald der Server dieses Paket empfangen hat, kann er die Verbindung selbst zwangsweise schließen, wenn Sie dies wünschen.

Theoobe
quelle
4
Ein praktisches Beispiel auf der Serverseite, wie dieses Hybi-Paket verwaltet wird.
Albanx
9
Es scheint verrückt, dass es die Verbindung nicht schließt. Die WebSocket-Variable wird beim erneuten Laden der Seite gelöscht. Warum sollte die Verbindung also offen bleiben, wenn nicht auf sie zugegriffen werden kann? Die Wiederverwendung der Verbindung wäre ebenfalls nicht sinnvoll.
Triynko
@ Albanx überprüfen Sie meine Antwort unten
artkoenig
Alle Codebeispiele zum Senden von Close Frames von einem Websocket-Client (z. B. Browser). Ich benutze ws npm Modul
Shaik Syed Ali
3

Wie von theoobe erwähnt , schließen einige Browser die Websockets nicht automatisch. Versuchen Sie nicht, Ereignisse "Browserfenster schließen" clientseitig zu behandeln. Es gibt derzeit keine zuverlässige Möglichkeit, dies zu tun, wenn Sie die Unterstützung der wichtigsten Desktop- UND mobilen Browser in Betracht ziehen (z. B. onbeforeunloadfunktioniert dies nicht in Mobile Safari). Ich hatte gute Erfahrungen mit der serverseitigen Behandlung dieses Problems. Wenn Sie beispielsweise Java EE verwenden, sehen Sie sich javax.websocket.Endpoint an . Je nach Browser wird entweder die OnCloseMethode oder die OnErrorMethode aufgerufen, wenn Sie das Browserfenster schließen / neu laden.

artkoenig
quelle
1
In meinem Fall wird die Verbindung während der Datenübertragung geschlossen. Dies funktioniert gut bei Browsern der Opera- und iOS-Familie. Bitte helfen Sie mir. Ich kämpfe seit zwei Wochen mit diesem Problem. stackoverflow.com/q/30799814/2225439
Mrug
2

Mit der Close-Methode des Web-Sockets können Sie jede Funktion nach Bedarf schreiben.

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