Fechando o WebSocket corretamente (HTML5, Javascript)


127

Estou brincando com HTML5 WebSockets. Fiquei me perguntando, como faço para fechar a conexão normalmente? Como, o que acontece se o usuário atualiza a página ou apenas fecha o navegador?

Há um comportamento estranho quando um usuário atualiza a página sem chamar websocket.close()- quando ele retorna após a atualização, o websocket.oncloseevento é atingido .

Respostas:


110

De acordo com a especificação de protocolo v76 (que é a versão que o navegador com suporte atual implementa):

Para fechar a conexão corretamente, um quadro que consiste em apenas um byte de 0xFF seguido por um byte de 0x00 é enviado de um ponto para solicitar que o outro ponto feche a conexão.

Se você estiver escrevendo um servidor, envie um quadro próximo quando o servidor fechar uma conexão de cliente. Às vezes, o método normal de fechamento do soquete TCP pode ser lento e fazer com que os aplicativos pensem que a conexão ainda está aberta, mesmo quando não está.

O navegador deve realmente fazer isso quando você fecha ou recarrega a página. No entanto, você pode garantir que um quadro próximo seja enviado capturando o evento beforeunload:

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

Não sei como você pode obter um evento onclose após a atualização da página. O objeto websocket (com o manipulador onclose) não existirá mais assim que a página for recarregada. Se você está tentando estabelecer imediatamente uma conexão WebSocket em sua página à medida que a página é carregada, pode estar ocorrendo um problema em que o servidor está recusando uma nova conexão logo após a desconexão da antiga (ou o navegador não está pronto para fazer conexões no ponto em que você está tentando se conectar) e você está recebendo um evento onclose para o novo objeto websocket.


2
É possível que, no Firefox, a conexão pareça permanecer na próxima página carregada. Não consigo encontrar uma referência, mas acho que pode ter havido um erro sobre isso. A outra possibilidade é que o oncloseevento seja acionado inesperadamente, ou talvez de propósito, à medida que o usuário navega / página é recarregada. Eu postei uma pergunta perguntando o que o comportamento esperado deve ser, qual navegador tem direito e como vamos implementar auto-reconexão.
leggetter

4
considerar estes problemas com onbeforeunloadevento
artkoenig


35

O fato é que existem duas versões principais de protocolo do WebSockets em uso hoje. A versão antiga que usa o [0x00][message][0xFF]protocolo, e há a nova versão usando pacotes formatados Hybi .

A versão antiga do protocolo é usada pelo Opera e iPod / iPad / iPhones, portanto, é realmente importante que a compatibilidade com versões anteriores seja implementada nos servidores WebSockets. Com esses navegadores usando o protocolo antigo, descobri que atualizar a página ou navegar para fora da página ou fechar o navegador resultam no fechamento automático da conexão. Ótimo!!

No entanto, com navegadores que usam a nova versão do protocolo (por exemplo, Firefox, Chrome e, eventualmente, IE10), apenas o fechamento do navegador resultará no fechamento automático da conexão. Ou seja, se você atualizar a página ou sair da página, o navegador NÃO fechará automaticamente a conexão. No entanto, o que o navegador faz é enviar um pacote hybi para o servidor com o primeiro byte (o proto ident) sendo 0x88(mais conhecido como quadro de dados próximo). Depois que o servidor recebe esse pacote, ele pode forçar o fechamento da conexão, se você escolher.


4
um exemplo prático no lado do servidor, como gerenciar esse pacote hybi?
albanx

9
Parece insano que não feche a conexão. A variável WebSocket é eliminada no recarregamento da página. Por que a conexão permaneceria aberta se não puder ser acessada? Reutilizar a conexão também não faria sentido.
Triynko

@albanx verificar a minha resposta abaixo
artkoenig

Qualquer amostra de código sobre como enviar quadro fechado a partir de um cliente de websocket (ou seja, Navegador). Estou usando o módulo ws NPM
Shaik Syed Ali

3

Conforme mencionado pelo theoobe , alguns navegadores não fecham os websockets automaticamente. Não tente manipular nenhum evento "fechar a janela do navegador" no lado do cliente. Atualmente, não há uma maneira confiável de fazê-lo, se você considerar o suporte aos principais navegadores de desktop e móveis (por exemplo onbeforeunload, não funcionará no Mobile Safari). Tive uma boa experiência em lidar com esse problema do lado do servidor. Por exemplo, se você usa Java EE, dê uma olhada em javax.websocket.Endpoint , dependendo do navegador, o OnClosemétodo ou o OnErrormétodo será chamado se você fechar / recarregar a janela do navegador.


1
No meu caso, o Connection está sendo fechado durante a transferência de dados. Funciona bem no caso dos navegadores Opera e iOS. Por favor me ajude. Estou lutando com esse problema desde as últimas duas semanas. stackoverflow.com/q/30799814/2225439
Mrug

2

Usando o método close do soquete da web, onde você pode escrever qualquer função de acordo com os requisitos.

var connection = new WebSocket('ws://127.0.0.1:1337');
    connection.onclose = () => {
            console.log('Web Socket Connection Closed');
        };
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.