Socket.io: Exceptions JS levées alors qu'il était juste inactif (WebSocket est déjà à l'état CLOSING ou CLOSED.)

Créé le 26 mai 2018  ·  55Commentaires  ·  Source: socketio/socket.io

Vous voulez:

  • [x] signaler un bogue
  • [ ] demander une fonctionnalité

Comportement actuel

Tout en laissant un socket connecté, mais en ne faisant aucune autre activité dans mon programme, je vois par intermittence (mais assez régulièrement) une exception levée dans la console du navigateur, depuis l'intérieur de la machinerie socket.io (en particulier dans backo2/index.js ligne 83. Cette erreur est :

WebSocket is already in CLOSING or CLOSED state.

socket-io-errors

Étapes à reproduire (si le comportement actuel est un bogue)

J'ai deux onglets ouverts avec des sockets client connectés au même serveur (localhost) via https. Les deux clients sont inactifs et rien d'autre ne se passe dans le navigateur ou le serveur (à l'exception de ce que fait socket.io). Les deux sont joints à un seul canal (via join(..) sur le serveur). Sinon, rien d'autre de spécial.

Voici comment je crée l'instance de socket du serveur :

var httpsServer = https.createServer(..);
var io = require("socket.io")(httpsServer);
io.on("connection",onSocketConnection);

Et dans le client :

socket = io();
socket.on("connect",function(){
   console.log("socket connected");
});
socket.on("disconnect",function(){
   console.log("socket disconnected");
});

Comportement attendu

Je m'attends à des déconnexions et des reconnexions de temps en temps, mais je ne m'attends pas à de fausses exceptions JS lancées par la bibliothèque lorsque je ne fais rien d'autre sur les connexions.

Installer

  • Système d'exploitation : Mac OSX
  • navigateur : Chrome 66, nœud 10.2.1
  • version socket.io : 2.1.1

Autres informations (par exemple, stacktraces, problèmes connexes, suggestions de résolution)

Trace de pile étendue :

index.js:83 WebSocket is already in CLOSING or CLOSED state.
(anonymous) @ index.js:83
e.encodePacket @ index.js:83
(anonymous) @ index.js:83
r.write @ index.js:83
r.send @ index.js:83
r.flush @ index.js:83
r.sendPacket @ index.js:83
r.ping @ index.js:83
(anonymous) @ index.js:83
setTimeout (async)
r.setPing @ index.js:83
r.onPacket @ index.js:83
(anonymous) @ index.js:83
r.emit @ index.js:83
r.onPacket @ index.js:83
r.onData @ index.js:83
ws.onmessage @ index.js:83

Commentaire le plus utile

Il y a un changement pour le pingTimeout par défaut de 60000 (v2.0.4) à 5000 (v2.1.0+) ce qui n'est pas suffisant pour certains navigateurs comme Chrome.

La solution à ce problème sur la v2.1.0+, y compris la dernière v2.2.0, consiste à remplacer le pingTimeout par défaut sur votre serveur par une valeur élevée comme suit :

const http = require('http');
const server = http.createServer();
const io = require('socket.io')(server, {
  pingTimeout: 60000,
});

OU

const io = require('socket.io')();
const http = require('http');
const server = http.createServer();
io.attach(server, {
  pingTimeout: 60000,
});

Tous les 55 commentaires

Je rencontre absolument le même problème et le code est correct. Cela ne se produit que dans Chrome pour moi. Mozilla est propre. En chrome, cette erreur pleut encore et encore et reproduit toutes les discussions que j'ai. J'ai essayé d'utiliser cette méthode
socket.on('disconnect', () =>{ socket.disconnect(); });
Il ne déconnecte pas le client du serveur. Dépôt en cas de besoin https://github.com/antoniab123456/Chat_app

le même problème ici
image

le navigateur est simplement inactif, puis les erreurs apparaissent.

J'ai utilisé Chrome et mac OS

Oui les gars, quelqu'un peut-il répondre à cela? Peut-être avons-nous besoin d'une autre ligne de code pour résoudre ce problème ?

J'ai le même problème avec socket.io et Chrome
MacOS 10.13.5
Chrome Version 67.0.3396.87 (version officielle) (64 bits)
Nœud : 10.3.0
Express : 4.16.3
socket.io : 2.1.1

Dans Firefox, tout va bien.

Détails de l'erreur ci-dessous :

index.js:83 WebSocket is already in CLOSING or CLOSED state.
(anonymous) | @ | index.js:83
  | e.encodePacket | @ | index.js:83
  | (anonymous) | @ | index.js:83
  | r.write | @ | index.js:83
  | r.send | @ | index.js:83
  | r.flush | @ | index.js:83
  | r.sendPacket | @ | index.js:83
  | r.ping | @ | index.js:83
  | (anonymous) | @ | index.js:83
  | setTimeout (async) |   |  
  | r.setPing | @ | index.js:83
  | r.onPacket | @ | index.js:83
  | (anonymous) | @ | index.js:83
  | r.emit | @ | index.js:83
  | r.onPacket | @ | index.js:83
  | r.onData | @ | index.js:83
  | ws.onmessage | @ | index.js:83

Lorsque je clique sur index.js:83, cela m'amène à ce module :

/**
 * Expose `Backoff`.
 */

module.exports = Backoff;

/**
 * Initialize backoff timer with `opts`.
 *
 * - `min` initial timeout in milliseconds [100]
 * - `max` max timeout [10000]
 * - `jitter` [0]
 * - `factor` [2]
 *
 * <strong i="16">@param</strong> {Object} opts
 * <strong i="17">@api</strong> public
 */

function Backoff(opts) {
  opts = opts || {};
  this.ms = opts.min || 100;
  this.max = opts.max || 10000;
  this.factor = opts.factor || 2;
  this.jitter = opts.jitter > 0 && opts.jitter <= 1 ? opts.jitter : 0;
  this.attempts = 0;
}

/**
 * Return the backoff duration.
 *
 * <strong i="18">@return</strong> {Number}
 * <strong i="19">@api</strong> public
 */

Backoff.prototype.duration = function(){
  var ms = this.ms * Math.pow(this.factor, this.attempts++);
  if (this.jitter) {
    var rand =  Math.random();
    var deviation = Math.floor(rand * this.jitter * ms);
    ms = (Math.floor(rand * 10) & 1) == 0  ? ms - deviation : ms + deviation;
  }
  return Math.min(ms, this.max) | 0;
};

/**
 * Reset the number of attempts.
 *
 * <strong i="20">@api</strong> public
 */

Backoff.prototype.reset = function(){
  this.attempts = 0;
};

/**
 * Set the minimum duration
 *
 * <strong i="21">@api</strong> public
 */

Backoff.prototype.setMin = function(min){
  this.ms = min;
};

/**
 * Set the maximum duration
 *
 * <strong i="22">@api</strong> public
 */

Backoff.prototype.setMax = function(max){
  this.max = max;
};

/**
 * Set the jitter
 *
 * <strong i="23">@api</strong> public
 */

Backoff.prototype.setJitter = function(jitter){
  this.jitter = jitter;
};




//////////////////
// WEBPACK FOOTER
// ./~/backo2/index.js
// module id = 41
// module chunks = 0

La ligne 83 est :

this.jitter = jitter;

J'ai en quelque sorte le même problème, avec backo2.js et à la ligne 83. voici mon erreur :
index.js:83 Uncaught TypeError : Échec de l'exécution de 'readAsArrayBuffer' sur 'FileReader' : le paramètre 1 n'est pas de type 'Blob'.
à n (index.js:83)
à n (index.js:83)
à n (index.js:83)
à n (index.js:83)
à n (index.js:83)
à n (index.js:83)
à Object.e.removeBlobs (index.js:83)
à s (index.js:83)
à r.encode (index.js:83)
à r.paquet (index.js:83)
et ne vous inquiétez pas des autres choses, elles sont toutes à la ligne 83, soit this.jitter = jitter;
Cela m'énerve tellement qu'il n'y a pas vraiment de solution dans google.

Quelqu'un a-t-il trouvé une solution provisoire ? @antoniab123456 avez-vous pu réparer votre application de chat afin qu'elle ne duplique pas vos chats ? Ça me fait la même chose.

Installer
Système d'exploitation : Mac OSX
Navigateur : Chrome 67.0.3396.99 (version officielle) (64 bits)
Noeud v10.5.0
Socket.io v2.1.1

Je suis confronté au problème exact @getify mentionné dans chrome. Quelqu'un at-il trouvé un travail autour de cela?

Même problème. Quelqu'un peut-il répondre à cela s'il vous plaît?

Même problème.

Installer
Système d'exploitation : Mac OSX
navigateur : Chrome 67.0.3396.99 (version officielle) (64 bits), Node 9.6.1
version socket.io : 2.1.1

@ 19smitgr idk ce que vous entendez par « discussions en double », ce qui semble hors sujet et pourrait être résolu en diffusant à la place si vous voulez dire « message en double sur le même écran ».

@kino2007 Je ne fais pas d'application de chat. J'utilise en fait des websockets avec un jeu multijoueur, et le websocket ne recevait pas de message de déconnexion, donc lorsque l'utilisateur se déconnecte et se reconnecte en raison de l'erreur aléatoire dont tout le monde parle, cela donnerait au personnage un nouvel ID de socket, et l'ancien sprite avec l'ancien ID de socket n'a pas été supprimé car il recevait simplement un message "transport close" au lieu d'un message "disconnect".

À ce stade, même si je reçois un message "fermer le transport", je supprime simplement l'utilisateur de ma liste d'utilisateurs actuels de la même manière que si j'avais reçu un message "déconnecter".

Même erreur ici

Après une recherche rapide, j'ai découvert que backo2 provoquait l'erreur.

Ensuite, j'ai utilisé la version de développement de socket.io et j'ai découvert que Socket.prototype.onevent génère l'erreur.

Je l'ai corrigé pour moi :

Auparavant, j'utilisais ceci :

socket.on('ping', alert);

Mais ensuite je l'ai changé en ceci:

socket.on('ping', msg => {
    alert(msg);
});

Et ça a marché !

J'ai le même problème. Des mises à jour à ce sujet ?

Pareil ici.

socket.io & socket.io-client : "^2.1.1"
Mac OS
Google Chrome est à jour
Version 68.0.3440.106 (version officielle) (64 bits)

J'ai le même problème. De plus, cela duplique les messages que j'envoie du serveur au client.

screen shot 2018-08-30 at 4 51 49 pm

Mac OS : 10.13.6
Socket.io : "^2.1.1"
Chrome : 68.0.3440.106

@abhyuditjain Vous pouvez essayer de réinitialiser tous les auditeurs en utilisant socket.removeAllListeners(); pour éviter plusieurs enregistrements d'auditeurs qui pourraient provoquer la duplication des messages.

Cela semble être un problème récurrent pour plusieurs personnes et il n'y a pas eu de solution à ce problème. Des mises à jour de quelqu'un?

@vkotu Si je supprime tous les écouteurs, le socket ne se reconnecte pas au serveur lors de la déconnexion. Aucun moyen de réparer cela?

utilisez simplement websocket-node, il est facile à utiliser et fonctionne sans aucune erreur et en plus vous n'avez pas besoin d'une bibliothèque externe pour cela :
https://codeburst.io/why-you-don-t-need-socket-io-6848f1c871cd
https://medium.com/@martin.sikora/node-js-websocket-simple-chat-tutorial-2def3a841b61
https://www.npmjs.com/package/websocket

pas une publicité, juste pour aider, à moins que vous n'ayez une décision pour cette erreur :DDD ça dure depuis des mois05.09.2018, 13h15, "Abhyudit Jain" [email protected] :@antoniab123456 dépôt. Veuillez ne pas faire de publicité ici.

—Vous recevez ceci parce que vous avez été mentionné.Répondez directement à cet e-mail, consultez-le sur GitHub ou désactivez le fil de discussion.

-- Cordialement, Antonia B. Spécialiste du service client @amoCRM Global

La rétrogradation à 2.0.3 a "résolu" ce problème pour moi.

@cozuya va le tester. Vous fera savoir si cela a fonctionné!

La rétrogradation à 2.0.3 a "résolu" ce problème pour moi.

semble faire l'affaire. Testé pendant 4 minutes et aucune erreur. A voir combien de temps ça tient !

@cozuya merci d'avoir posté ça !

Même erreur en 2.1.1

Le passage à la version 2.0.3 a "résolu" ce problème pour moi.

2.0.3 fonctionne pour moi! Merci @cozuya

2.1.1 toujours confrontés aux mêmes problèmes. J'ai essayé d'augmenter le ping et le délai d'attente mais rien n'a changé

avoir le même problème dans chrome avec v2.1.1, alors que le navigateur est inactif pendant une longue période (environ 20-30 minutes)

2.1.1 toujours confrontés aux mêmes problèmes. J'ai essayé d'augmenter le ping et le délai d'attente mais rien n'a changé

rétrograder vers v 2.0.3

J'ai essayé d'utiliser socket.io avec 2.0.4, cela semble normal.

J'ai trouvé qu'il y a un changement pour le pingTimeout de 60000 (v2.0.4) à 5000 (v2.1.1)

Si j'ai changé pingTimeout en un nombre plus grand comme 10000, cela semble fonctionner.

Je suppose que cela peut être lié à l'inactivité du navigateur où l'onglet inactif aura un certain accélérateur.

J'ai eu un problème. Quelqu'un a-t-il résolu le problème ?

J'ai dû rétrograder aussi. Cela ne fonctionnait pas pour chrome et safari

Même problème ici. Chrome sous OSX.

Je travaille autour de cela en n'utilisant pas socket.removeAllListeners(); mais socket.off("whatever") pour tous mes auditeurs non techniques en plus "disconnect" et ainsi de suite. Fonctionne bien. Les messages d'erreur dans la console du navigateur sont ennuyeux mais ne valent pas une rétrogradation pour moi.

Je dois dire que c'est décevant de voir ce problème sans aucune attention. C'est six mois et ça compte.

Donc, la raison de la reconnexion est le délai d'expiration du ping pour moi. Même avec la rétrogradation, je reçois toujours l'erreur.

Je suis complètement d'accord avec une bibliothèque aussi énorme avec une base de code étendue mais aucune attention à ce problème!

J'espère que quelqu'un s'y mettra bientôt!

Envoyé de mon iPhone

Le 28 novembre 2018, à 14h14, HorseBadorties [email protected] a écrit :

Même problème ici. Chrome sous OSX.

Je le contourne sans utiliser socket.removeAllListeners(); mais socket.off("whatever") pour tous mes auditeurs non techniques en plus de "disconnect" et ainsi de suite. Fonctionne bien. Les messages d'erreur dans la console du navigateur sont ennuyeux mais ne valent pas une rétrogradation pour moi.

Je dois dire que c'est décevant de voir ce problème sans aucune attention. C'est six mois et ça compte.


Vous recevez ceci parce que vous avez commenté.
Répondez directement à cet e-mail, consultez-le sur GitHub ou désactivez le fil de discussion.

Même problème.... surpris qu'aucune solution n'ait encore été apportée à ce problème.

J'ai rencontré ce problème. Dans mon cas, la déconnexion était due à ping timeout . Cependant, aucune chance de savoir pourquoi le côté client a cessé de répondre aux pings.

io.on('connection', function(socket) {
  socket.on('disconnect', function(reason) {
  console.log(`Socket disconnected for: ${reason}`);
  }
});

https://socket.io/docs/server-api/#Event -%E2%80%98disconnect%E2%80%99 contient une liste des raisons des déconnexions.

Plus de débogage :
image
Une observation est que l'événement ping sur le client est +30s du dernier. Chaque fois que j'ai vu la déconnexion, c'était 30s+ qui est l'intervalle de pulsation par défaut + le délai d'expiration du ping. +26s , +28s et +29s se sont affichés sans déconnexion.
Lors de la comparaison avec Safari, Safari était plus cohérent sur le ping tous les 25s et n'a vu aucune déconnexion.

Il y a un changement pour le pingTimeout par défaut de 60000 (v2.0.4) à 5000 (v2.1.0+) ce qui n'est pas suffisant pour certains navigateurs comme Chrome.

La solution à ce problème sur la v2.1.0+, y compris la dernière v2.2.0, consiste à remplacer le pingTimeout par défaut sur votre serveur par une valeur élevée comme suit :

const http = require('http');
const server = http.createServer();
const io = require('socket.io')(server, {
  pingTimeout: 60000,
});

OU

const io = require('socket.io')();
const http = require('http');
const server = http.createServer();
io.attach(server, {
  pingTimeout: 60000,
});

Pourquoi 5000 ne suffisent pas ? Je vois ce problème sur mon serveur de développement local, et la latence entre le client et le serveur est certainement inférieure à ce seuil. 5000 ms semble être un délai raisonnable. On dirait qu'il pourrait y avoir un problème avec le système de ping-pong lui-même, et cela ne s'est manifesté que lorsqu'il a été abaissé.

Merci d'avoir lancé ce fil @getify (je suis sur socket.io v2.2.0)

À tous ceux qui vivent également cela - ME TOO COMMENTAIRES N'AIDENT PAS :-) s'il vous plaît votez pour le problème avec un pouce pour montrer votre soutien 👍

Merci @omardoma d'avoir découvert le pingTimeout et je suis d'accord avec @LunarMist que nous devrions enquêter sur le système d'événements ping/pong .

J'ai fait quelques tests préliminaires avec Chrome, Firefox et Safari (tous sur MacOS).

Chrome et Safari semblent tous deux limiter l'activité de ws avec des comportements et des contraintes différents :

  • Chrome, après ~5min d'inactivité lorsque l'onglet est focalisé ou immédiatement lorsque l'onglet passe en arrière-plan. Ceci est intentionnel par l'équipe de chrome (https://developers.google.com/web/updates/2017/03/background_tabs)
  • Safari, presque immédiatement lorsque le focus de l'application est modifié pour une autre application de bureau (MacOS) ou lorsque l'onglet passe en arrière-plan. Lié à #2924
  • Firefox, * n'a jamais aucun problème mentionné dans ce fil

Solutions

J'ai testé pendant plusieurs heures avec ces 3 navigateurs, en changeant les valeurs pingTimeout & pingInterval . Ce que j'ai trouvé comme solutions :

  1. Réglage pingTimeout >= 30000 ms

    • ou -

  2. Réglage pingInterval <= 10000 ms

Je crois que la meilleure solution est de changer pingTimeout = 30000 . La valeur par défaut pingInterval est 25000 ms et l'augmentation de la fréquence des clients pingant le serveur à toutes les 10 secondes peut être trop bavarde pour les projets _à grande échelle_.


@darrachequesne ou tout autre membre du dépôt sont-ils en faveur de l'augmentation de la valeur par défaut pingTimeout à 30000 par rapport à la valeur par défaut actuelle de 5000 ms qui a été modifiée dans la v2.1 de 60000 ms ?

Réagir à votre propre commentaire n'aide pas non plus.

Ce sont les clients qui envoient un ping au serveur et non l'inverse.

Je pense que c'est parce que la version actuelle de socket.io repose sur le setTimeout côté client, qui peut ne pas être aussi fiable que prévu.

Je pense que l'augmentation du pingTimeout devrait résoudre temporairement le problème, mais nous utiliserons ping/pong depuis le serveur -> client (au lieu du client actuel -> serveur) dans la v3.

Utilisez simplement le code suivant côté client.

_socket.on('ping', () => {
socket.emit(data);
});_

Merci @crobinson42 ! La solution de délai d'attente de ping a très bien fonctionné pour moi. J'ai juste quelques inquiétudes au sujet de cette solution. Si vous avez perdu la connexion Internet à tout moment, il faudra jusqu'à 30 secondes pour que l'événement de déconnexion soit déclenché et pour certaines applications, c'est trop. par exemple, une application de chat qui souhaite désactiver la saisie de texte lorsque l'utilisateur n'est pas connecté.

Dans ce cas, augmenter l'intervalle de ping ferait le travail, mais comme vous l'avez dit, le coût est élevé, existe-t-il une solution de contournement pour cela ?

S'il vous plaît laissez-nous savoir une fois que cela est corrigé, même problème pour moi, mes versions r ci-dessous:

"socket.io": "2.2.0",
"socket.io-adapter": "~1.1.1",
"socket.io-client": "2.2.0",
"socket.io-parser": "~3.2.0",
"socket.io-redis": "^5.2.0",

Mon code :
serveur, {
chemin : '/socket.io',
serveClient : vrai,
// ci-dessous sont les options engine.IO
pingInterval : 40000,
pingTimeout : 25 000,
upgradeTimeout : 30 000, // la valeur par défaut est de 10 000 ms, essayez de la remplacer par 20 000 ou plus
mandataire : faux,
cookie : faux,
rejeterNon autorisé : faux,
délai de reconnexion : 1000,
reconnexionDelayMax: 5000
}

mon client:

reconnexion : vrai,
délai de reconnexion : 1000,
reconnectionDelayMax: 5000,
tentatives de reconnexion : Infini,
//options de notre site
transports : ["polling", "websocket"],
sécurisé : vrai,
rejeterNon autorisé : faux,
forceNouveau : vrai,
délai d'attente : 60 000

Bonjour Faizan,
Vous pouvez faire fonctionner ce code comme -
** J'ai utilisé la même version que celle que vous avez donnée..

Côté serveur - Code :

serveur const = require('http').createServer();
const io = require('socket.io')(serveur, {
// chemin : '/socket.io',
serveClient : vrai,

pingInterval: 40000,
pingTimeout: 25000,
upgradeTimeout: 21000, // default value is 10000ms, try changing it to 20k or more
agent: false,
cookie: false,
rejectUnauthorized: false,
reconnectionDelay: 1000,
reconnectionDelayMax: 5000

});

io.on('connexion', fonction(socket) {
socket.emit('bienvenue', { message : 'Bienvenue !', id : socket.id });
socket.on('Sunil', console.log);
});

serveur.écoute(3000);

Code côté client :

var client = require("socket.io-client");
var socket = client.connect("http://localhost:3000", {
reconnexion : vrai,
délai de reconnexion : 1000,
reconnectionDelayMax: 5000,
tentatives de reconnexion : Infini,
transports : ["websocket"],
sécurisé : faux,
rejeterNon autorisé : faux,
forceNouveau : vrai,
délai d'attente : 6000
});

socket.connect();
socket.emit('Sunil', {
données : 'Bonjour'
});
socket.on('bienvenue', fonction (données) {
console.log(données)
socket.emit('Sunil', {
données : 'Faizan',
id : data.id
});

socket.disconnect();

});

Salutations
Sunil Yadav

Le 9 mai 2019, à 16h05, Faizan Zahid [email protected] a écrit :

reconnexion : vrai,
délai de reconnexion : 1000,
reconnectionDelayMax: 5000,
tentatives de reconnexion : Infini,
//options de notre site
transports : ["polling", "websocket"],
sécurisé : vrai,
rejeterNon autorisé : faux,
forceNouveau : vrai,
délai d'attente : 60 000

Peut-être une solution de contournement côté client si quelqu'un est intéressé jusqu'à ce que le problème soit résolu. Cela empêchera le navigateur de libérer de la mémoire et pourrait entraîner une utilisation excessive de la mémoire.

  • Comme indiqué ici, https://apple.stackexchange.com/questions/344183/safari-12-mac-does-includeinternaldebugmenu-1-still-work , accordez d'abord à l'application Terminal un accès complet au disque localement et redémarrez le terminal.
  • Ouvrez une fenêtre de terminal, collez et exécutez la commande defaults write com.apple.Safari IncludeInternalDebugMenu 1
  • Redémarrez Safari. Vous verrez un nouveau menu Debug en haut à droite.
  • Sous Debug->Miscellaneous Flags, activez deux drapeaux "Disable App Nap" et "Disable Hidden Page Timer Throttling" et redémarrez Safari.

Si quelqu'un a une solution de contournement pour Chrome, cela aiderait

Vous utilisez Safari pour le webdev localhost ? 🤔

Vous utilisez Safari pour le webdev localhost ? 🤔

Pas vraiment, mais c'est ennuyeux avec des déconnexions constantes pour tester mon application. Cela fournit une solution de contournement temporaire jusqu'à ce qu'elle soit corrigée dans la version 3.0. Ce n'est pas une solution. J'ai posté si cela pouvait aider quelqu'un pendant le développement.

J'utilise un pingInterval et des pingTimeouts très bas pour obtenir des changements d'état hors ligne en temps réel, le régler à 30 secondes interromprait mon flux ... est-ce que quelqu'un connaît un moyen de résoudre ce problème afin que je puisse utiliser le "correctif" de longue durée pour le navigateur en arrière-plan onglets ?

Des mises à jour à ce sujet ?

J'utilise un pingInterval et des pingTimeouts très bas pour obtenir des changements d'état hors ligne en temps réel, le régler à 30 secondes interromprait mon flux ... est-ce que quelqu'un connaît un moyen de résoudre ce problème afin que je puisse utiliser le "correctif" de longue durée pour le navigateur en arrière-plan onglets ?

Vous devriez est les événements de déconnexion sur le socket pour gérer la présence, lorsque le socket se déconnecte, trouvez l'utilisateur et marquez-le comme hors ligne dans votre magasin de données

Voici les valeurs par défaut de la documentation. On dirait qu'un ping est envoyé toutes les 25 secondes et que chaque ping a 5 secondes pour se terminer.

pingTimeout | 5000 | combien de ms sans paquet pong pour considérer la connexion fermée
-- | -- | --
pingInterval | 25000 | combien de ms avant d'envoyer un nouveau paquet ping

J'ai remarqué cette même erreur mais dans un contexte différent, je vais donc faire une brève description de mon problème et de la solution pour tous ceux qui se retrouvent ici.

Mon scénario était sur Chrome pour Android où la connexion est interrompue après le verrouillage de l'écran.

J'utilise un jeton pour identifier le même utilisateur sur différentes connexions, que j'envoie du client lors de la connexion en utilisant l' approche de l'option de requête et je mets à jour le jeton avec un nouveau reçu du serveur :

// client
io('myAppUrl', {
  query: {
    token: localStorage.getItem('myKey') || ''
  }
});

io.on('reconnect_attempt', () => {
  io.opts.query = {
    token: localStorage.getItem('myKey') || ''
  };
});

io.on('my_custom_connection_successful_event', (token) => {
  localStorage.setItem('myKey', token);
});

Le problème est que le client Chrome pour Android enverrait au serveur un jeton de chaîne vide lors de la reconnexion. Ce à quoi je ne m'attendais pas depuis que j'ai ajouté l'écouteur 'reconnect_attempt' qui s'assure de définir le dernier jeton à partir de localStorage .

Eh bien, après quelques heures de débogage avec la console enregistrant tous les événements clients possibles, j'ai réalisé que l'événement 'reconnect_attempt' n'était pas du tout déclenché dans mon scénario de reconnexion. Après avoir déverrouillé l'écran, j'obtiens la séquence d'événements suivante :

  • déconnecter (raison : 'transport fermé')
  • reconnexion (tentative : 1)
  • se reconnecter
  • le ping/pong recommence

Ainsi, aucun événement 'reconnect_attempt' n'est déclenché, ce qui explique pourquoi le jeton est toujours une chaîne vide (la valeur initiale définie lors de la connexion).

Pour faire court, la solution pour moi est de mettre immédiatement à jour la variable d'instance io.opts.query sur mon événement personnalisé "connexion réussie" reçu du serveur avec le nouveau jeton :

// client
io('myAppUrl', {
  query: {
    token: localStorage.getItem('myKey') || ''
  }
});

io.on('my_custom_connection_successful_event', (token) => {
  localStorage.setItem('myKey', token);
  io.opts.query = {
    token: token
  };
});

Maintenant, je comprends que io.opts.query est une variable d'instance qui est utilisée lors de la connexion et de toutes les reconnexions ultérieures, donc je peux la mettre à jour dès que je le souhaite. Je n'ai pas besoin d'attendre un événement lié à la reconnexion.

Je me sens un peu induit en erreur par la documentation With query options . Peut-être ai-je mal compris le cas d'utilisation dans cet exemple? Mais si cela ressemble à mon cas d'utilisation, au lieu de l'exemple 'reconnect_attempt' , la documentation pourrait expliquer que io.opts.query est une variable d'instance qui peut être mutée et que sa valeur actuelle est utilisée lors de toutes les reconnexions ultérieures. Il peut donc être modifié chaque fois que vous souhaitez actualiser le jeton, même sur un événement personnalisé 'refresh_token' par exemple. Je peux faire un PR si vous pensez que c'est une bonne idée pour améliorer les docs.

Éditer:
Après une enquête plus approfondie, j'ai réalisé que mon erreur était que l'écouteur 'reconnect_attempt' était supprimé d'une autre partie de mon code... :man_facepalming: C'est pourquoi je ne le voyais pas dans ma journalisation. Alors oui, la séquence d'événements pour mon scénario de reconnexion est en fait :

  • déconnecter (raison : 'transport fermé')
  • reconnect_attempt (tentative : 1)
  • reconnexion (tentative : 1)
  • se reconnecter
  • le ping/pong recommence

Pourtant, ma réalisation que io.opts.query peut être changé quand vous le souhaitez est toujours valable. :sweat_smile:

Est-il toujours possible de rétrograder ? Je passe sur 2.0.3 mais cela ne semble pas fonctionner.

Bonjour, je suis confronté au même genre de problème mais avec deux erreurs. J'ai essayé la solution @omardoma . Quelqu'un peut-il aider?
Système d'exploitation - Ubuntu 18.04
Nœud - 12.16.2
npm - 6.14.5
socket.io - 2.3.0
mon code-

app.js

const speech = require('@google-cloud/speech');
const speechClient = new speech.SpeechClient(); // Creates a client
const environmentVars = require('dotenv').config();
const io = require('socket.io')();
const http = require('http');
const server = http.createServer();
io.attach(server, {
  pingTimeout: 60000,
});



console.log(io)



// =========================== SOCKET.IO ================================ //

io.on('connection', function (client) {
  console.log('Client Connected to server');
  let recognizeStream = null;

fichier ejs

<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.3.0/socket.io.js" integrity="sha256-bQmrZe4yPnQrLTY+1gYylfNMBuGfnT/HKsCGX+9Xuqo=" crossorigin="anonymous"></script>
<script src="/js/client.js"></script>

fichier js

const socket = io.connect("http://localhost:8080");

J'utilise socket.io version 2.3.0. J'utilise une connexion websocket au client. Lorsque mon client a une alerte de navigateur (qui est synchrone) dans l'interface utilisateur et si l'utilisateur ne rejette pas l'alerte pendant plus de 30 secondes (pingTimeout + pingInterval), je vois le message "Websocket est déjà dans l'état CLOSING ou CLOSED" et j'obtiens un événement de déconnexion avec la raison pingTimeout. Je ne veux pas que ce websocket se déconnecte lorsque l'interface utilisateur a une alerte. Si j'augmente le pingTimeout à 10 min, la déconnexion ne se produit pas pendant 10 min. Mais d'après ce que j'ai lu dans les commentaires ci-dessus, cela peut avoir un impact négatif (le client peut ne pas savoir qu'il y a eu une déconnexion avant 10 minutes). Mais j'ai remarqué que s'il y a une interruption du réseau, etc., nous obtenons une déconnexion avec une raison de fermeture du transport. Est-il donc acceptable d'augmenter ce pingTimeout + pingInterval ? Existe-t-il un scénario spécifique lorsqu'une déconnexion n'est pas détectée ? Ou y a-t-il un autre moyen de résoudre ce problème ?

Cette page vous a été utile?
0 / 5 - 0 notes