obtendo o motivo pelo qual os websockets foram fechados com o código de fechamento 1006

94

Eu gostaria de obter o motivo do fechamento dos websockets, para que eu possa mostrar a mensagem certa ao usuário.

eu tenho

sok.onerror=function (evt) 
     {//since there is an error, sockets will close so...
       sok.onclose=function(e){
           console.log("WebSocket Error: " , e);}

O código é sempre 1006 e o ​​motivo é sempre "". Mas eu quero diferenciar os diferentes motivos de fechamento.

Por exemplo, a linha de comando fornece um motivo de erro: "você não pode excluir isso, porque o banco de dados não permite". Mas no console do Chrome, o motivo ainda é "".

Existe alguma outra maneira de diferenciar os diferentes motivos de fechamento?

Slevin
fonte
Acho que isso se deve à forma como o servidor está lidando com os eventos conectados / desconectados. Não sei dizer ao certo mas o fechamento da conexão precisa ser feito corretamente no servidor também com código. Tente substituir os métodos On Connected / Disconnected integrados no servidor e veja. Minha suposição é apenas que você está fechando, mas o servidor não está fechando corretamente e, portanto, não está retransmitindo a resposta fechada adequada.
Michael Puckett II

Respostas:

125

Close Code1006 é um código especial que significa que a conexão foi fechada de forma anormal (localmente) pela implementação do navegador.

Se o seu cliente de navegador relatar código de fechamento 1006, você deve examinar o websocket.onerror(evt)evento para obter detalhes.

No entanto, o Chrome raramente relatará quaisquer 1006motivos de fechamento de código para o lado do Javascript. Provavelmente, isso se deve às regras de segurança do cliente nas especificações do WebSocket para evitar o abuso do WebSocket. (como usá-lo para verificar portas abertas em um servidor de destino ou para gerar muitas conexões para um ataque de negação de serviço).

Observe que o Chrome frequentemente relatará um código de fechamento 1006se houver um erro durante a atualização HTTP para o Websocket (esta é a etapa antes de um WebSocket ser tecnicamente "conectado"). Por motivos como autenticação ou autorização incorreta ou uso de protocolo incorreto (como solicitação de um subprotocol, mas o próprio servidor não suporta o mesmo subprotocol), ou até mesmo uma tentativa de falar com um local de servidor que não seja um WebSocket como tentar se conectar a ws://images.google.com/)

Fundamentalmente, se você 1006vir um código fechado , terá um erro de nível muito baixo com o próprio WebSocket (semelhante a "Não foi possível abrir o arquivo" ou "Erro de soquete"), que não é realmente destinado ao usuário, pois aponta para um problema de baixo nível com seu código e implementação. Corrija seus problemas de baixo nível e, quando estiver conectado, poderá incluir códigos de erro mais razoáveis. Você pode fazer isso em termos de escopo ou gravidade em seu projeto. Exemplo: informações e nível de aviso fazem parte do protocolo específico do seu projeto e não fazem com que a conexão seja encerrada. Com relatórios de mensagens graves ou fatais, também usando o protocolo do seu projeto para transmitir quantos detalhes você deseja e, em seguida, fechando a conexão usando as capacidades limitadas do fluxo de fechamento do WebSocket.

Esteja ciente de que os códigos de fechamento do WebSocket são definidos de forma muito estrita e a frase / mensagem do motivo do fechamento não pode exceder 123 caracteres de comprimento (esta é uma limitação intencional do WebSocket).

Mas nem tudo está perdido, se você está querendo essas informações apenas por motivos de depuração, os detalhes do fechamento e seu motivo subjacente são frequentemente relatados com uma quantidade razoável de detalhes no console Javascript do Chrome.

Joakim Erdfelt
fonte
4
Joakim, obrigado, anser muito detalhado. Se eu usar sok.onerror=function (evt) {console.log(evt);}os detalhes não são tantos. Nem mesmo um reasonou algo assim. Então, nenhuma opção? Acabei de mostrar ao usuário, something is wrong, or not connencted?Não é tão amigável, seria bom se o usuário pudesse ver "Você não pode excluir, por causa das restrições do banco de dados". Alguma opção? Obrigado
slevin
Em sok.onclosevez disso, você deve usar os gatilhos close eventque tem reasone codenele
Ihab Khattab
@IhabKhattab que seria específico do código de fechamento e também quando o fechamento ocorrer. ter sok.onclosefuncionará para muitos caminhos, mas não todos os caminhos. Especialmente protocolo ruim, erros de handshake ruins (como algumas condições que podem causar fechamento de código 1006). Isso mudará no futuro? Provavelmente. Mas quando essa resposta foi escrita, era verdade.
Joakim Erdfelt
@JoakimErdfelt desculpe, eu estava respondendo a @slevin pergunta sobre ele não tenha reasonretornado quando ele usou onerrorEu estava apontando que este propriedades codee reasonespecífica para closeevento não errorevento. então seria melhor para ele usar onclose, estou faltando alguma coisa?
Ihab Khattab
@IhabKhattab sim, pois sua pergunta era específica sobre o código de erro 1006que tem um significado especial e tratamento especial na especificação do websocket e na API javascript do websocket. O motivo da string / mensagem em algumas 1006condições não é exposta de maneira específica e intencional em nenhum lugar da API. (como a resposta apontou). Este não é um bug na API, ele apenas aborda as várias especificações e suas preocupações sobre o abuso de websocket para fins não-websocket.
Joakim Erdfelt
19

No meu e possivelmente no caso do @BIOHAZARD foi nginx proxy timeout. Por padrão é 60seg sem atividade no soquete

Mudei para 24h nginxe resolveu o problema

proxy_read_timeout 86400s;
proxy_send_timeout 86400s;
MixerOID
fonte
Obrigado por isso! É a razão do erro 1006 no meu caso.
Steve Hanov,
11

Parece que este é o caso quando o Chrome não é compatível com o padrão WebSocket. Quando o servidor inicia o fechamento e envia o quadro fechado para um cliente, o Chrome considera isso um erro e relata para o lado JS com o código 1006 e nenhuma mensagem de motivo. Em meus testes, o Chrome nunca responde a frames de fechamento iniciados pelo servidor (código de fechamento 1000), sugerindo que o código 1006 provavelmente significa que o Chrome está relatando seu próprio erro interno.

PS Firefox v57.00 lida com este caso adequadamente e entrega com sucesso a mensagem de razão do servidor para o lado do JS.

user10663464
fonte
4

Achei que isso poderia ser útil para outros. Saber regex é útil, crianças. Fique na escola.

Edit: Transformou-o em uma função dândi útil!

let specificStatusCodeMappings = {
    '1000': 'Normal Closure',
    '1001': 'Going Away',
    '1002': 'Protocol Error',
    '1003': 'Unsupported Data',
    '1004': '(For future)',
    '1005': 'No Status Received',
    '1006': 'Abnormal Closure',
    '1007': 'Invalid frame payload data',
    '1008': 'Policy Violation',
    '1009': 'Message too big',
    '1010': 'Missing Extension',
    '1011': 'Internal Error',
    '1012': 'Service Restart',
    '1013': 'Try Again Later',
    '1014': 'Bad Gateway',
    '1015': 'TLS Handshake'
};

function getStatusCodeString(code) {
    if (code >= 0 && code <= 999) {
        return '(Unused)';
    } else if (code >= 1016) {
        if (code <= 1999) {
            return '(For WebSocket standard)';
        } else if (code <= 2999) {
            return '(For WebSocket extensions)';
        } else if (code <= 3999) {
            return '(For libraries and frameworks)';
        } else if (code <= 4999) {
            return '(For applications)';
        }
    }
    if (typeof(specificStatusCodeMappings[code]) !== 'undefined') {
        return specificStatusCodeMappings[code];
    }
    return '(Unknown)';
}

Uso:

getStatusCodeString(1006); //'Abnormal Closure'

{
    '0-999': '(Unused)',
    '1016-1999': '(For WebSocket standard)',
    '2000-2999': '(For WebSocket extensions)',
    '3000-3999': '(For libraries and frameworks)',
    '4000-4999': '(For applications)'
}

{
    '1000': 'Normal Closure',
    '1001': 'Going Away',
    '1002': 'Protocol Error',
    '1003': 'Unsupported Data',
    '1004': '(For future)',
    '1005': 'No Status Received',
    '1006': 'Abnormal Closure',
    '1007': 'Invalid frame payload data',
    '1008': 'Policy Violation',
    '1009': 'Message too big',
    '1010': 'Missing Extension',
    '1011': 'Internal Error',
    '1012': 'Service Restart',
    '1013': 'Try Again Later',
    '1014': 'Bad Gateway',
    '1015': 'TLS Handshake'
}

Fonte (com pequenas edições para concisão): https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent#Status_codes

Andrew
fonte
Que tal um pacote npm? :-)
Piranna
@Piranna Vá em frente. ;)
André
1

Recebi o erro ao usar o Chrome como cliente e golang gorilla websocket como servidor no proxy nginx

E enviar apenas uma mensagem "ping" do servidor para o cliente a cada x segundo resolveu o problema

RISCO BIOLÓGICO
fonte
0

Pode ser que o URL do seu websocket que você está usando no dispositivo não seja o mesmo (você está acessando um URL do websocket diferente de android / iphonedevice)

Ankush Sahu
fonte