Chiusura corretta di WebSocket (HTML5, Javascript)


127

Sto giocando con HTML5 WebSocket. Mi chiedevo, come posso chiudere la connessione con garbo? Ad esempio, cosa succede se l'utente aggiorna la pagina o chiude semplicemente il browser?

C'è un comportamento strano quando un utente aggiorna semplicemente la pagina senza chiamare websocket.close()- quando ritornano dopo l'aggiornamento colpirà l' websocket.oncloseevento.

Risposte:


110

Secondo la specifica del protocollo v76 (che è la versione del browser con l'attuale supporto implementare):

Per chiudere la connessione in modo pulito, un frame costituito da un byte 0xFF seguito da un byte 0x00 viene inviato da un peer per chiedere che l'altro peer chiuda la connessione.

Se si sta scrivendo un server, è necessario assicurarsi di inviare un frame vicino quando il server chiude una connessione client. Il normale metodo di chiusura del socket TCP a volte può essere lento e indurre le applicazioni a pensare che la connessione sia ancora aperta anche quando non lo è.

Il browser dovrebbe davvero farlo per te quando chiudi o ricarichi la pagina. Tuttavia, puoi assicurarti che venga inviato un frame vicino catturando l'evento beforeunload:

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

Non sono sicuro di come ottenere un evento onclose dopo l'aggiornamento della pagina. L'oggetto websocket (con il gestore onclose) non esisterà più una volta ricaricata la pagina. Se stai provando immediatamente a stabilire una connessione WebSocket sulla tua pagina mentre la pagina viene caricata, potresti riscontrare un problema in cui il server rifiuta una nuova connessione così presto dopo che quella precedente si è disconnessa (o il browser non è pronto per effettuare connessioni nel punto in cui si sta tentando di connettersi) e si sta ottenendo un evento onclose per il nuovo oggetto websocket.


2
È possibile che in Firefox la connessione sembri bloccarsi nel caricamento della pagina successiva. Non riesco a trovare un riferimento, ma penso che potrebbe esserci stato un bug al riguardo. L'altra possibilità è che l' oncloseevento venga attivato in modo imprevisto, o forse apposta, quando l'utente naviga / pagina viene ricaricata. Ho pubblicato una domanda che chiede quale dovrebbe essere il comportamento previsto, quale browser ha ragione e come implementiamo la riconnessione automatica.
leggetter

4
considerare questi problemi con l' onbeforeunloadevento
artkoenig il


35

Il fatto è che ci sono 2 versioni principali del protocollo di WebSocket in uso oggi. La vecchia versione che utilizza il [0x00][message][0xFF]protocollo e poi c'è la nuova versione usando i pacchetti formattati Hybi .

La vecchia versione del protocollo è utilizzata da Opera e iPod / iPad / iPhone, quindi è in realtà importante implementare la retrocompatibilità nei server WebSocket. Con questi browser che utilizzano il vecchio protocollo, ho scoperto che l'aggiornamento della pagina, la navigazione dalla pagina o la chiusura del browser, provocano automaticamente la chiusura della connessione. Grande!!

Tuttavia, con i browser che utilizzano la nuova versione del protocollo (ad es. Firefox, Chrome e infine IE10), solo la chiusura del browser comporterà la chiusura automatica della connessione. Vale a dire, se si aggiorna la pagina o ci si allontana dalla pagina, il browser NON chiude automaticamente la connessione. Tuttavia, ciò che fa il browser è inviare un pacchetto hybi al server con il primo byte (il proto ident) essendo 0x88(meglio noto come il vicino frame di dati). Una volta che il server riceve questo pacchetto, può chiudere forzatamente la connessione stessa, se lo si desidera.


4
un esempio pratico sul lato server come gestire questo pacchetto hybi?
albanx

9
Sembra folle che non chiuda la connessione. La variabile WebSocket viene cancellata al ricaricamento della pagina, quindi perché la connessione rimarrebbe aperta se non fosse possibile accedervi? Anche il riutilizzo della connessione non avrebbe senso.
Triynko,

@albanx controlla la mia risposta qui sotto
artkoenig

Qualsiasi esempio di codice su come inviare frame ravvicinati da un client websocket (ad es. Browser). Sto usando il modulo ws npm
Shaik Syed Ali,

3

Come accennato da theoobe , alcuni browser non chiudono automaticamente i websocket. Non tentare di gestire alcun evento "Chiudi finestra del browser" sul lato client. Al momento non esiste un modo affidabile per farlo, se si considera il supporto dei principali browser desktop e mobili (ad es. onbeforeunloadNon funzionerà in Mobile Safari). Ho avuto una buona esperienza nella gestione di questo problema lato server. Ad esempio, se usi Java EE, dai un'occhiata a javax.websocket.Endpoint , a seconda del browser verrà chiamato il OnClosemetodo o il OnErrormetodo se chiudi / ricarichi la finestra del browser.


1
Nel mio caso, la connessione si sta chiudendo durante il trasferimento dei dati, funziona bene nel caso dei browser della famiglia Opera e iOS. Per favore, aiutatemi. Sto combattendo con questo problema dalle ultime due settimane. stackoverflow.com/q/30799814/2225439
Mrug

2

Usando il metodo vicino di web socket, in cui è possibile scrivere qualsiasi funzione in base alle esigenze.

var connection = new WebSocket('ws://127.0.0.1:1337');
    connection.onclose = () => {
            console.log('Web Socket Connection Closed');
        };
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.