Socket.io: Plusieurs prises ouvertes après reconnexion

Créé le 28 juil. 2011  ·  54Commentaires  ·  Source: socketio/socket.io

J'ai remarqué cela à la fois sur mon application socket.io et sur celle de quelqu'un d'autre. Lorsqu'une reconnexion se produit, il est courant que plus d'un socket dans un client soit ouvert, ce qui ne devrait jamais se produire.

Voici un journal que j'ai obtenu de ma propre application de test lorsque j'ai eu une déconnexion / reconnexion.

** Déconnecter* * Reconnexion avec délai 1000 tentatives: 1
** Reconnexion avec délai de 2000 tentatives: 2* * Connexion avec xhr-polling
** Connexion avec xhr-polling* * Reconnectez-vous avec les tentatives d'interrogation xhr de type transport: 2
** Connecté* * Connecté

Lorsque cela se produit, je reçois des messages en double envoyés, un pour chaque socket connectée, même s'il ne devrait y en avoir qu'un. Il est confirmé par Firebug qu'il y a, en fait, deux sockets du client connectés. Ma meilleure hypothèse est que cela se trouve dans le code client, peut-être ne ferme pas la première tentative de reconnexion.

Bien sûr, la vraie question pourrait être pourquoi y a-t-il eu une déconnexion en premier lieu?

Socket.IO client bug

Commentaire le plus utile

En enquêtant un peu plus loin, il semble que j'ai trouvé ce qui a causé mes problèmes. Ce n'est pas un bug , mais une mauvaise implémentation du code côté client de ma part. facepalm Voici ce que j'avais à l'origine:

PROBLÈME:

var socket = io.connect();

socket.on('connect', function () {

  console.log('User connected!');

  socket.on('message', function(message) {

    console.log(message);

  });

});

Le JavaScript côté client ci-dessus a provoqué plusieurs appels à console.log () lorsque le ou les clients se sont reconnectés. C'est ce que j'ai remplacé par:

SOLUTION:

var socket = io.connect();

socket.on('connect', function () {

  console.log('User connected!');

});

socket.on('message', function(message) {

  console.log(message);

});

Désormais, plusieurs messages ne sont pas envoyés dans les deux sens lorsque les clients se reconnectent au serveur. Quelqu'un d'autre peut-il confirmer qu'une modification de son code côté client résout le problème?

Tous les 54 commentaires

La déconnexion est déclenchée car techniquement, le client s'est déconnecté du serveur. Et est déconnecté jusqu'à ce que l'événement de reconnexion soit déclenché à nouveau.

Mais le reste est un bug.

Je pense que c'est aussi la raison d'un bug dans mon application -

Du côté du serveur, j'ai créé un curseur disponible sur mongodb pour se déclencher à chaque fois qu'il y a un nouvel insert. Ce message est ensuite envoyé via io.sockets.emit () à toutes les personnes connectées.

Mais au lieu de recevoir un seul message par événement, je reçois plusieurs messages répétés du côté client.

Je suis sur une connexion Internet extrêmement peu fiable, donc je suppose que ce bogue affecte également mon code.

Est-ce que vous utilisiez expressjs? J'ai eu ce problème avec express, je l'ai réécrit sans et cela a bien fonctionné.

Express n'aurait absolument rien à voir avec ce @mfkp , devait faire quelque chose de bizarre

D'accord avec @visionmedia , c'est un bogue dans socket.io pas avec Express. Parce que l'implémentation actuelle de reconnexion était toujours conçue pour la version 0.6, il manque donc quelques vérifications et nettoyages.

Ah, je vois. Nevermind, continuez ;-)

+1 à cela. Problème intermittent dans notre application de chat où socket.io ouvre plusieurs connexions. Le client reçoit alors des dupes de toutes les émissions.

+1. Websockets et chrome. L'ordinateur portable se met en veille -> l'application se reconnecte après le réveil -> double événements. Se produit uniquement lors de la connexion au serveur distant. Impossible de reproduire cela localement, il doit y avoir un problème de reconnexion / latence réseau.

y a-t-il une solution de contournement pour se débarrasser de la connexion multiple après cela ?, par exemple du côté client, si je fais socket.disconnect (), est-ce qu'il déconnectera toutes les connexions? Comme je veux éviter plusieurs mises à jour. le suivant fonctionne-t-il?
socket = io.connect (url)
socket.on ('connecter', fonction () {
if (multipleConnect) {
socket.disconnect ();
socket.removeAllListeners ('connect');
io.sockets = {};
socket = io.connect (url);
socket.on ('connect', functionToConnect);
}
})

Veuillez lire ceci https://github.com/LearnBoost/socket.io/issues/474#issuecomment -2833227.
Il explique pourquoi ce bogue se produit et comment il peut être reproduit.

@ 3rd-Eden - Une idée de l'endroit où ce correctif se situe dans votre liste de tâches / priorités? J'ai une application que je construis et j'avais l'intention de l'utiliser pour cela, et j'aimerais pouvoir dire à mon client qu'il se reconnectera correctement à partir des appareils iOS. Il se déconnecte une fois que l'application est mise en arrière-plan ou que l'appareil est mis en veille.

Ou avez-vous une idée de la façon dont je peux coder une solution de contournement? J'ai travaillé sur quelques choses ces derniers jours, mais le meilleur des cas semble toujours laisser trop de connexions ouvertes et supprimer toutes les données stockées sur les sockets. Les données ne sont pas la fin du monde. Je peux utiliser le déclencheur de reconnexion du client pour résoudre ce problème, mais les connexions simultanées sont un peu laides.

Merci!

@cris Je ne suis pas sûr que ce soit le même bug que vous mentionnez. J'ai un exemple très simple du bogue sans ralentissement sur le serveur.

Je peux clairement reproduire ce problème en:

  1. Implémentez un client de pulsation simple qui envoie des pulsations toutes les 1 seconde d'intervalle.
  2. Comptez le nombre de nouvelles connexions côté serveur.
  3. Comptez le nombre de déconnexions côté serveur.
  4. Démarrez le serveur et établissez une connexion avec un client.
  5. Interrompez la connexion réseau entre le client et le serveur.
  6. Attendez que le serveur expire et émette un événement de déconnexion.
  7. Reconnectez la connexion réseau.

Observez que lorsque le client se reconnecte, il crée 2 à 4 connexions en émettant un événement «connect» pour chacune. Le serveur reçoit 2 à 4 connexions du client et émet un événement de «connexion» pour chacune. Le client ne ferme jamais aucune des connexions mal démarrées.

Merci. Je pense vraiment que ce bug devrait être une priorité. De nombreuses entreprises commerciales qui ne connaissent pas mieux essaient d'embaucher des personnes pour se développer contre le framework socket.io, pensant que cela fonctionne bien. Certes, socket.io est gratuit, alors peut-être que ces entreprises commerciales devraient commencer à chercher des produits commerciaux. Mais encore une fois, je pense que cela doit vraiment être considéré comme une priorité très élevée. Ce bogue existe depuis la 0.7.0 et est facilement reproductible.

@davidfooks , @theyak. J'ai résolu ce problème pour moi il y a longtemps et cela fonctionne sans problème.

Pour réparer, vous devez:

  1. Appliquer ce patch: https://github.com/LearnBoost/socket.io-client/pull/342
  2. Désactivez la prise de contact AJAX (et laissez la prise de contact uniquement via JSONP), comme décrit dans le commentaire de demande d'extraction.

Comment désactiver la négociation AJAX? Je suppose que vous pouvez toujours utiliser tous les types de connexion, cela n'affectera que la poignée de main?

+1 s'il vous plaît résoudre ce problème :)

J'ai eu le même problème de connexion multiple lors de la reconnexion. Je pense que c'est un problème grave ...
La cause est que la méthode Socket.connect est appelée mais que l'indicateur de connexion n'est défini sur true qu'une fois la négociation terminée, au cas où l'un des minuteries matbeReconnect (minuteries gérant la reconnexion) se réveillerait pendant le processus de prise de contact, il appellera Socket. se reconnecter provoquant plusieurs reconnexions.
J'ai résolu le problème en appelant self.reconnecting au début de la méthode Socket.connect.

Une chance de fusionner cela?
Ce bogue crée également un mauvais bogue dans mon application.

Ce bogue existe toujours. J'ai essayé les deux patchs. Sans succès.

+1 J'ai souvent ce problème en utilisant xhr-polling Je n'ai pas encore essayé les correctifs

+1, j'ai aussi ce problème avec les reconnexions en double.

Chaque fois que Node.js est redémarré (c'est-à-dire lors de l'exécution via superviseur), mon (mes) client (s) se reconnectent X fois le nombre de fois que Node.js a été redémarré à partir du point où le (s) client (s) se sont connectés initialement. Le bogue provoque l'émission d'événements une fois par reconnexion du côté client - ce n'est pas seulement une question de doublons.

J'ai essayé socket.on('disconnect', function() { socket.disconnect(); }); côté client, mais cela ne fonctionne pas. : /

En enquêtant un peu plus loin, il semble que j'ai trouvé ce qui a causé mes problèmes. Ce n'est pas un bug , mais une mauvaise implémentation du code côté client de ma part. facepalm Voici ce que j'avais à l'origine:

PROBLÈME:

var socket = io.connect();

socket.on('connect', function () {

  console.log('User connected!');

  socket.on('message', function(message) {

    console.log(message);

  });

});

Le JavaScript côté client ci-dessus a provoqué plusieurs appels à console.log () lorsque le ou les clients se sont reconnectés. C'est ce que j'ai remplacé par:

SOLUTION:

var socket = io.connect();

socket.on('connect', function () {

  console.log('User connected!');

});

socket.on('message', function(message) {

  console.log(message);

});

Désormais, plusieurs messages ne sont pas envoyés dans les deux sens lorsque les clients se reconnectent au serveur. Quelqu'un d'autre peut-il confirmer qu'une modification de son code côté client résout le problème?

Salut. J'ai eu le même problème. Lorsque je redémarrais le nœud (ou lorsque la connexion expirait) et que le client se reconnectait, je recevais le même message émis par le serveur à n fois (où n était le nombre de reconnexions).
J'ai résolu ce problème en déplaçant tous mes gestionnaires de l'intérieur du socket.on ('connect' function () {...}); fonction à l'extérieur de celui-ci.

Le code ci-dessus fait ce qu'il faut.
Voici ma réponse complète de la liste de diffusion:
https://groups.google.com/forum/?hl=fr&fromgroups#!topic/socket_io/X9FRMjCkPco

@xdanx , génial, merci pour la réponse.

oui, cela semble fonctionner pour moi aussi: mettre le code socket.on ('message') séparé du code d'événement 'connect'

Mais qu'en est-il de "Connection"?
Et qu'en est-il de l'objet "socket" dans le callback?

/ edit Nevermind, je vois, 'connect' est sur le client. J'avais toujours des problèmes avec le spam de reconnexion alors que je ne l'avais pas fait. Mais c'était en 0.9.6

Je semble avoir le même problème aussi ... J'ai essayé le correctif ci-dessus de déplacer le code de message pour séparer les blocs ... mais j'ai remarqué que je ne l'ai jamais eu ensemble.

des nouvelles sur d'autres solutions de contournement pour cela dans la 0.9.8?

J'ai le même problème. J'ai 0.9.10 installé. Aucun moyen de réparer cela? :(
btw cela fait plus d'un an et pas encore de solution .. :(

ÉDITER.

Le problème semble avoir disparu lorsque je n'utilise que jsonp-polling.
io.set ('transports', ['jsonp-polling']);

J'ai le même problème.
prise. [email protected]
nœud v0.8.8

@semprom Je pense que l'utilisation de jsonp-polling le corrige car cela pourrait ne concerner que les connexions websocket.

Malheureusement pour moi, toute ma mise en œuvre repose sur le fait que les commentaires soient aussi rapides que possible, donc les Websockets, par opposition au sondage, fonctionnent mieux, et comme je contrôle les clients qui se connectent, je ne vois aucune raison, à part ce problème, de passer à quoi que ce soit. autre.

Notez que les connexions multiples du même client qui se reconnectent ont le même socket.id . Ainsi, vous pouvez gérer votre propre liste d'identifiants de socket et ignorer les doublons pour contourner ce problème.

@KasperTidemann Merci. Cela a résolu ce problème.

@esanai Pas de problème, content que cela ait fonctionné!

Salut, j'ai le même problème et j'ai remarqué qu'à chaque fois que la connexion est reconnectée, un nouvel identifiant de socket client est créé. La solution est soit d'utiliser io.set ('transports', ['jsonp-polling']); ou utiliser la solution de KasperTidemann?

@KasperTidemann Mon Dieu, mec, c'est exactement la réponse à mes problèmes! Voir ce commit: https://github.com/samuelclay/NewsBlur/commit/76cbbd8d8b2a787985bba724dc3562108492b017#L2L3887

Je peux reproduire à volonté un événement de double connexion suite à une erreur de connexion avec ce simple code client et serveur dans un seul fichier node.js:

"use strict";

var server = require('socket.io');
var client = require('socket.io-client');

setTimeout(function () {
    var io = server.listen(8888);

    io.of('/chat').on('connection', function (socket) {
        console.log('Server: /chat connection');
        socket.emit('greeting', 'Hello, who are you?');
    });

    io.sockets.on('connection', function (socket) {
        console.log('Server: connection');
    });
}, 2000);

var socketAddress = 'http://localhost:8888/chat';
var socket = client.connect(socketAddress);

socket.on('connect', function () {
    console.log("Client: connect");
});

socket.on('greeting', function (data) {
    console.log("Client: greeting: ", data);
});

socket.on('error', function () {
    console.log("Client: error");
    socket.socket.reconnect();
});

Des travaux à faire ou des correctifs en vue?

Désolé, j'ai également publié ceci dans le numéro 474.

Je peux reproduire cette erreur de manière assez cohérente en utilisant un iPhone avec iOS 9.3.2 et Chrome Version 50.0.2661.95 et sur Safari pour iOS avec la version 1.4.6 de Socket.IO

Je ne peux reproduire cela que sur mobile et il accroche ma page à la requête à socket.io.

J'ai un simple .on ('connect', function (socket) {console.log ('Connected');}); et il enregistre Connecté deux fois lorsque l'erreur se produit, ce qui me porte à croire qu'il essaie d'ouvrir plusieurs connexions de socket en même temps.

screenshot 2016-05-27 13 03 44

Est-ce que quelqu'un connaît une solution de contournement pour cela?

Pourquoi ce problème a-t-il été résolu?

Mon exemple de code du 14 avril 2014 ci-dessus ne produit plus d'événements de double connexion. Il existe un événement de connexion pour «/ chat» et un pour le socket lui-même. Ce qui semble raisonnable.

Il n'y a également plus d'erreur, même dans le client.

C'est avec socket.io 1.4.8 et le nœud 6.3.0.

Ce bug m'affecte atm.

Apparemment, lorsque les socket_handlers sont placés avec des routes, ils sont appelés plusieurs fois. Utilisez la connexion socket dans app.js et exigez des gestionnaires dans la connexion socket, passez le socket en tant que paramètre. Notez que certaines propriétés peuvent ne pas être fournies avec l'instance de socket

@leemlwando veuillez ouvrir un nouveau numéro si nécessaire.

J'ai eu le même problème que de créer une fonction de reconnexion manuelle sur le client et d'appeler io.destroy (); à l'intérieur de la fonction de reconnexion, cela a résolu le problème.

Merci beaucoup @leemlwando Votre dernier commentaire m'a permis de résoudre mes problèmes.

Je reçois toujours ce bogue, y a-t-il une mise à jour?

Je pense que le seul vrai bogue ici est qu'Internet est plein de mauvais exemples de code où les appels socket.on () sont enveloppés dans le gestionnaire socket.on ('connect'). Chaque fois que le socket se reconnecte, de nouvelles instances des gestionnaires sont empilées au-dessus de celles existantes, ce qui entraîne plusieurs appels à chaque événement. Ne faites pas ça: voir la réponse de @KasperTidemann du 25 juillet 2012.

Peut-être DrLexO, sauf que le code que j'ai présenté ci-dessus a démontré le problème. Il n'a pas de socket.on () encapsulé dans un gestionnaire socket.on ('connect').

Après toutes ces années, j'ai été surpris d'être encore informé de ce bug. Je ne sais pas si c'est encore une chose ou pas. Dois-je réessayer?

@KasperTidemann merci, cela a en fait résolu le problème.

Comment pouvez-vous définir vos écouteurs d'événement _en dehors_ de l'auditeur connect lorsque vous n'avez pas accès au socket ?

const app = express();
const http = require('http').createServer(app);
const io = require('socket.io')(http);

io.on('connect', function(socket) {

  // only now that we are inside the connect callback do we have access to the socket

  socket.on('join', function(room, user) {
  });

  socket.on('add_message', function(room, user) {
  });

  socket.on('disconnect', function(room, user) {
  });
});

Les gens semblent suggérer que les auditeurs d'événements ( join , add_message et disconnect ) devraient vivre indépendamment, _à l'extérieur_ de l'auditeur connect , mais comment est-ce possible sans socket cours de définition?

io.on('connect', function(socket) {
  // socket is only available here
});

// socket is undefined here

socket.on('join', function(room, user) {
});

socket.on('add_message', function(room, user) {
});

socket.on('disconnect', function(room, user) {
});

Existe-t-il une manière différente d'instancier socket pour que cela soit possible?

Pourquoi est-ce fermé? @ michael-lynch a un point valide

J'aimerais également connaître la réponse au point de @ michael-lynch.

@ DrLex0 sur l'exemple de site Web socket.io, il montre même de faire ce qui suit:

io.on('connection', function(socket){
  socket.on('chat message', function(msg){
    io.emit('chat message', msg);
  });
});
Cette page vous a été utile?
0 / 5 - 0 notes

Questions connexes

Aweather picture Aweather  ·  4Commentaires

kootoopas picture kootoopas  ·  4Commentaires

thebinarypenguin picture thebinarypenguin  ·  4Commentaires

MichaelJCole picture MichaelJCole  ·  3Commentaires

varHarrie picture varHarrie  ·  3Commentaires