132 votes

Obtenir la raison pour laquelle les websockets se sont fermés avec le code de fermeture 1006

Je voudrais connaître la raison de la fermeture des WebSockets, afin de pouvoir afficher le bon message à l'utilisateur.

J'ai

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

Le code est toujours 1006 et la raison est toujours " ". Mais je veux pouvoir indiquer des raisons de fermeture différentes.

Par exemple, la ligne de commande donne une raison d'erreur : "vous ne pouvez pas supprimer cela, car la base de données ne vous le permet pas". Mais dans la console de Chrome, la raison est toujours " ".

Y a-t-il un autre moyen de distinguer les différentes raisons de fermeture ?

180voto

Joakim Erdfelt Points 9394

Code de fermeture 1006 est un code spécial qui signifie que la connexion a été fermée de manière anormale (en local) par l'implémentation du navigateur.

Si votre navigateur client signale le code de fermeture 1006, vous devez alors regarder l'événement websocket.onerror(evt) pour plus de détails.

Cependant, Chrome rapportera rarement des raisons de code de fermeture 1006 du côté JavaScript. Cela est probablement dû aux règles de sécurité-client dans la spécification WebSocket pour éviter les abus du WebSocket (comme l'utilisation pour scanner des ports ou générer beaucoup de connexions pour une attaque par déni de service).

Notez que Chrome signalera souvent un code de fermeture 1006 s'il y a une erreur pendant la mise à niveau HTTP vers WebSocket (c'est l'étape avant qu'un WebSocket soit techniquement "connecté"). Pour des raisons telles qu'une mauvaise authentification ou autorisation, ou une mauvaise utilisation du protocole (comme demander un sous-protocole, mais le serveur lui-même ne supporte pas ce même sous-protocole), ou même une tentative de parler à un emplacement de serveur qui n'est pas un WebSocket (comme tenter de se connecter à ws://images.google.com/)

Fondamentalement, si vous voyez un code de fermeture 1006, vous avez une erreur de bas niveau avec WebSocket lui-même (similaire à "Impossible d'ouvrir le fichier" ou "Erreur de socket"), pas vraiment destinée à l'utilisateur, car elle pointe vers un problème de bas niveau avec votre code et votre implémentation. Corrigez vos problèmes de bas niveau, puis lorsque vous êtes connecté, vous pouvez inclure des codes d'erreur plus raisonnables. Vous pouvez accomplir cela en termes de portée ou de gravité dans votre projet. Par exemple, les niveaux d'information et d'avertissement font partie du protocole spécifique de votre projet et ne provoquent pas la rupture de la connexion. Avec des messages sévères ou fatals signalant également à l'aide du protocole de votre projet autant de détails que vous le souhaitez, puis en fermant la connexion en utilisant les capaci...voir plus de contenu.

65voto

MixerOID Points 900

Dans mon cas et peut-être celui de @BIOHAZARD, c'était nginx proxy timeout. Par défaut, c'est 60 secondes sans activité dans la socket

Je l'ai changé à 24h dans nginx et cela a résolu le problème

proxy_read_timeout 86400s;
proxy_send_timeout 86400s;

19voto

user10663464 Points 199

Il semble que c'est le cas lorsque Chrome n'est pas conforme à la norme WebSocket. Lorsque le serveur initie la fermeture et envoie un cadre de fermeture à un client, Chrome considère cela comme une erreur et le signale au côté JS avec le code 1006 et aucun message de raison. Dans mes tests, Chrome ne répond jamais aux cadres de fermeture initiés par le serveur (code de fermeture 1000), ce qui suggère que le code 1006 signifie probablement que Chrome signale sa propre erreur interne.

P.S. Firefox v57.00 gère correctement ce cas et parvient à livrer avec succès le message de raison du serveur au côté JS.

17voto

Andrew Points 959

Je pensais que cela pourrait être utile pour les autres. Savoir utiliser les expressions régulières est utile, les enfants. Restez à l'école.

Édition: Je l'ai transformé en une fonction pratique!

let specificStatusCodeMappings = {
    '1000': 'Fermeture normale',
    '1001': 'Départ',
    '1002': 'Erreur de protocole',
    '1003': 'Données non prises en charge',
    '1004': '(Pour le futur)',
    '1005': 'Aucun statut reçu',
    '1006': 'Fermeture anormale',
    '1007': 'Données de charge utile de trame non valides',
    '1008': 'Violation de politique',
    '1009': 'Message trop long',
    '1010': 'Extension manquante',
    '1011': 'Erreur interne',
    '1012': 'Redémarrage du service',
    '1013': 'Réessayez plus tard',
    '1014': 'Passerelle incorrecte',
    '1015': 'Poignée de main TLS'
};

function getStatusCodeString(code) {
    if (code >= 0 && code <= 999) {
        return '(Inutilisé)';
    } else if (code >= 1016) {
        if (code <= 1999) {
            return '(Pour standard WebSocket)';
        } else if (code <= 2999) {
            return '(Pour les extensions WebSocket)';
        } else if (code <= 3999) {
            return '(Pour les bibliothèques et les frameworks)';
        } else if (code <= 4999) {
            return '(Pour les applications)';
        }
    }
    if (typeof(specificStatusCodeMappings[code]) !== 'undefined') {
        return specificStatusCodeMappings[code];
    }
    return '(Inconnu)';
}

Utilisation:

getStatusCodeString(1006); //'Fermeture anormale'

{
    '0-999': '(Inutilisé)',
    '1016-1999': '(Pour standard WebSocket)',
    '2000-2999': '(Pour les extensions WebSocket)',
    '3000-3999': '(Pour les bibliothèques et les frameworks)',
    '4000-4999': '(Pour les applications)'
}

{
    '1000': 'Fermeture normale',
    '1001': 'Départ',
    '1002': 'Erreur de protocole',
    '1003': 'Données non prises en charge',
    '1004': '(Pour le futur)',
    '1005': 'Aucun statut reçu',
    '1006': 'Fermeture anormale',
    '1007': 'Données de charge utile de trame non valides',
    '1008': 'Violation de politique',
    '1009': 'Message trop long',
    '1010': 'Extension manquante',
    '1011': 'Erreur interne',
    '1012': 'Redémarrage du service',
    '1013': 'Réessayez plus tard',
    '1014': 'Passerelle incorrecte',
    '1015': 'Poignée de main TLS'
}

Source (avec de légères modifications pour la concision): https://developer.mozilla.org/fr/docs/Web/API/CloseEvent#Codes_de_statut

8voto

BioHazard Points 338

J'ai reçu l'erreur en utilisant Chrome comme client et le websocket gorilla golang comme serveur sous un proxy nginx

Et envoyer simplement un message "ping" du serveur au client toutes les x secondes a résolu le problème

Mise à jour: Oh mec, j'ai mis en œuvre des dizaines d'applications basées sur le websocket après cette réponse et ENVOYER DES PING DU CLIENT toutes les 5 secondes est la bonne façon de maintenir la connexion avec le serveur active (je ne sais pas ce que j'avais en tête quand je recommandais de faire ping depuis le serveur)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X