Socket.io: Nach dem erneuten Anschließen öffnen sich mehrere Steckdosen

Erstellt am 28. Juli 2011  ·  54Kommentare  ·  Quelle: socketio/socket.io

Ich habe dies sowohl bei meiner socket.io-Anwendung als auch bei jemand anderem bemerkt. Wenn eine erneute Verbindung hergestellt wird, ist es üblich, dass mehr als ein Socket innerhalb eines Clients geöffnet ist, was niemals passieren sollte.

Hier ist ein Protokoll, das ich von meiner eigenen Testanwendung erhalten habe, als ich die Verbindung getrennt / wieder hergestellt habe.

** Trennen* * Wiederverbindung mit Verzögerung 1000 Versuche: 1
** Wiederverbindung mit Verzögerung 2000 Versuche: 2* * Verbindung mit xhr-polling herstellen
** Verbindung mit xhr-polling* * Wiederverbindung mit Transporttyp xhr-polling Versuche: 2
** In Verbindung gebracht* * Verbunden

In diesem Fall werden doppelte Nachrichten gesendet, eine für jeden angeschlossenen Socket, obwohl es nur eine geben sollte. Firebug bestätigt, dass tatsächlich zwei Sockets vom Client verbunden sind. Ich vermute, dass dies im Client-Code enthalten ist und möglicherweise den ersten Versuch der erneuten Verbindung nicht beendet.

Die eigentliche Frage könnte natürlich sein, warum es überhaupt eine Unterbrechung gab.

Socket.IO client bug

Hilfreichster Kommentar

Wenn ich das etwas weiter untersuche, habe ich anscheinend herausgefunden, was meine Probleme verursacht hat. Es ist kein Fehler , sondern eine falsche Implementierung des clientseitigen Codes von meiner Seite. facepalm Das hatte ich ursprünglich:

PROBLEM:

var socket = io.connect();

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

  console.log('User connected!');

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

    console.log(message);

  });

});

Das obige clientseitige JavaScript verursachte die mehrfachen Aufrufe von console.log (), als die Clients erneut eine Verbindung herstellten. Dies ist, was ich oben ersetzt habe durch:

LÖSUNG:

var socket = io.connect();

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

  console.log('User connected!');

});

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

  console.log(message);

});

Jetzt werden nicht mehrere Nachrichten hin und her gesendet, wenn Clients erneut eine Verbindung zum Server herstellen. Kann jemand anderes bestätigen, dass eine Änderung seines clientseitigen Codes das Problem behebt?

Alle 54 Kommentare

Die Trennung wird ausgelöst, da der Client technisch gesehen die Verbindung zum Server getrennt hat. Und wird getrennt, bis das Wiederverbindungsereignis erneut ausgelöst wird.

Aber der Rest ist ein Fehler.

Ich denke, dies ist auch der Grund für einen Fehler in meiner Anwendung -

Auf der Serverseite habe ich einen mailbaren Cursor auf mongodb erstellt, der jedes Mal ausgelöst wird, wenn eine neue Einfügung vorhanden ist. Diese Nachricht wird dann über io.sockets.emit () an alle verbundenen Personen gesendet.

Aber anstatt nur eine Nachricht pro Ereignis zu erhalten, erhalte ich auf der Clientseite mehrere Wiederholungsnachrichten.

Ich habe eine äußerst unzuverlässige Internetverbindung. Ich vermute also, dass dieser Fehler auch meinen Code betrifft.

Habt ihr Expressjs benutzt? Ich hatte dieses Problem mit Express, schrieb es ohne um und es funktionierte gut.

Express hätte absolut nichts mit diesem @mfkp zu tun, muss etwas

Einverstanden mit @visionmedia , es ist ein Fehler in socket.io, nicht mit Express. Da die aktuelle Neuverbindungsimplementierung noch für 0.6 ausgelegt war, fehlen einige Überprüfungen und Bereinigungen.

Ah ich sehe. Vergiss nicht, mach weiter ;-)

+1 dazu. Zeitweiliges Problem in unserer Chat-App, bei der socket.io mehrere Verbindungen öffnet. Der Client empfängt dann Dupes aller Emits.

+1. Websockets & Chrom. Laptop geht in den Ruhezustand -> App verbindet sich nach dem Aufwachen wieder -> doppelte Ereignisse. Passiert nur, wenn eine Verbindung zum Remote-Server hergestellt wird. Kann dies nicht lokal reproduzieren, muss ein Problem mit der Wiederverbindung / Netzwerklatenz sein.

Gibt es eine Problemumgehung, um danach mehrere Verbindungen zu entfernen? Wenn ich z. B. auf Client-Seite socket.disconnect () ausführe, werden dann alle Verbindungen getrennt? Da möchte ich mehrere Updates vermeiden. funktioniert folgendes?
Socket = io.connect (URL)
socket.on ('connect', function () {
if (multipleConnect) {
socket.disconnect ();
socket.removeAllListeners ('connect');
io.sockets = {};
Socket = io.connect (URL);
socket.on ('connect', functionToConnect);
}}
})

Bitte lesen Sie diese https://github.com/LearnBoost/socket.io/issues/474#issuecomment -2833227.
Es wird erklärt, warum dieser Fehler auftritt und wie er reproduziert werden kann.

@ 3rd-Eden - Hast du eine Idee, wo dieses Update auf deine Aufgabenliste / Prioritäten fällt? Ich habe eine App, die ich erstelle, und ich hatte vor, diese dafür zu verwenden, und würde gerne meinem Kunden mitteilen können, dass die Verbindung von iOS-Geräten wieder ordnungsgemäß hergestellt wird. Die Verbindung wird getrennt, nachdem die Anwendung in den Hintergrund gestellt oder das Gerät in den Ruhezustand versetzt wurde.

Oder haben Sie eine Idee, wie ich eine Problemumgehung codieren kann? Ich habe in den letzten Tagen an einigen Dingen gearbeitet, aber im besten Fall scheinen immer zu viele Verbindungen offen zu bleiben und alle gespeicherten Daten der Sockets zu löschen. Die Daten sind nicht das Ende der Welt. Ich kann den Auslöser für die erneute Verbindung vom Client verwenden, um dieses Problem zu lösen, aber die gleichzeitigen Verbindungen sind etwas hässlich.

Vielen Dank!

@cris Ich bin mir nicht sicher, ob dies der gleiche Fehler ist, den Sie erwähnen. Ich habe ein sehr einfaches Beispiel für den Fehler ohne Verlangsamung auf dem Server.

Ich kann dieses Problem klar reproduzieren, indem ich:

  1. Implementieren Sie einen einfachen Heartbeat-Client, der alle 1 Sekunde Heartbeats sendet.
  2. Zählen Sie die Anzahl der neuen Verbindungen auf der Serverseite.
  3. Zählen Sie die Anzahl der serverseitigen Verbindungsabbrüche.
  4. Starten Sie den Server und stellen Sie eine Verbindung mit einem Client her.
  5. Unterbrechen Sie die Netzwerkverbindung zwischen Client und Server.
  6. Warten Sie, bis der Server eine Zeitüberschreitung aufweist und ein Trennungsereignis ausgibt.
  7. Stellen Sie die Netzwerkverbindung wieder her.

Beachten Sie, dass der Client beim erneuten Verbinden 2-4 Verbindungen erstellt, die jeweils ein Verbindungsereignis auslösen. Der Server empfängt 2-4 Verbindungen vom Client und gibt für jede ein Verbindungsereignis aus. Der Client schließt niemals eine der falsch gestarteten Verbindungen.

Vielen Dank. Ich denke wirklich, dass dieser Fehler eine Priorität sein sollte. Viele kommerzielle Unternehmen, die es nicht besser wissen, versuchen, Mitarbeiter einzustellen, die sich gegen das Socket.io-Framework entwickeln, und denken, dass es gut funktioniert. Zugegeben, socket.io ist kostenlos. Vielleicht sollten sich diese kommerziellen Unternehmen mit kommerziellen Produkten befassen. Aber auch hier denke ich, dass dies wirklich als sehr hohe Priorität priorisiert werden muss. Dieser Fehler besteht seit 0.7.0 und ist leicht reproduzierbar.

@davidfooks , @theyak. Ich habe dieses Problem vor langer Zeit für mich behoben und es funktioniert ohne viel Aufhebens.

Um dies zu beheben, sollten Sie:

  1. Wenden Sie diesen Patch an: https://github.com/LearnBoost/socket.io-client/pull/342
  2. Deaktivieren Sie AJAX-Handshake (und lassen Sie Handshake nur über JSONP erfolgen), wie im Pull-Request-Kommentar beschrieben.

Wie deaktiviere ich AJAX Handshake? Ich gehe davon aus, dass Sie immer noch alle Verbindungstypen verwenden können. Dies wirkt sich nur auf den Handshake aus.

+1 bitte das beheben :)

Ich hatte das gleiche Problem mit mehreren Verbindungen beim erneuten Verbinden. Ich denke, das ist ein ernstes Problem ...
Die Ursache ist, dass die Socket.connect-Methode aufgerufen wird, das Conneting-Flag jedoch erst nach Abschluss des Handshakes auf true gesetzt wird. Wenn einer der matbeReconnect-Timer (Timer, die die Wiederverbindung verarbeiten) während des Handshake-Prozesses aufwacht, rufen sie Socket auf. Stellen Sie die Verbindung erneut her, wodurch mehrere Verbindungen hergestellt werden.
Ich habe das Problem gelöst, indem ich self.reconnecting am Anfang der Socket.connect-Methode aufgerufen habe.

Gibt es eine Chance, dies zusammenzuführen?
Dieser Fehler macht auch in meiner App einen schlechten Fehler.

Dieser Fehler besteht immer noch. Versuchte beide Patches. Kein Erfolg.

+1 Ich habe dieses Problem häufig mit xhr-polling. Ich habe die Patches noch nicht ausprobiert

+1, auch ich habe dieses Problem mit den doppelten Wiederverbindungen.

Bei jedem Neustart von Node.js (dh beim Ausführen über den Supervisor) stellen meine Clients die Verbindung X-mal so oft wieder her, wie Node.js an dem Punkt neu gestartet wurde, an dem die Clients ursprünglich verbunden waren. Der Fehler führt dazu, dass Ereignisse einmal pro erneuter Verbindung von der Clientseite ausgegeben werden - dies ist nicht nur eine Frage von Duplikaten.

Ich habe socket.on('disconnect', function() { socket.disconnect(); }); auf der Clientseite ausprobiert, aber das funktioniert nicht. : /

Wenn ich das etwas weiter untersuche, habe ich anscheinend herausgefunden, was meine Probleme verursacht hat. Es ist kein Fehler , sondern eine falsche Implementierung des clientseitigen Codes von meiner Seite. facepalm Das hatte ich ursprünglich:

PROBLEM:

var socket = io.connect();

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

  console.log('User connected!');

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

    console.log(message);

  });

});

Das obige clientseitige JavaScript verursachte die mehrfachen Aufrufe von console.log (), als die Clients erneut eine Verbindung herstellten. Dies ist, was ich oben ersetzt habe durch:

LÖSUNG:

var socket = io.connect();

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

  console.log('User connected!');

});

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

  console.log(message);

});

Jetzt werden nicht mehrere Nachrichten hin und her gesendet, wenn Clients erneut eine Verbindung zum Server herstellen. Kann jemand anderes bestätigen, dass eine Änderung seines clientseitigen Codes das Problem behebt?

Hallo. Ich hatte das gleiche Problem. Beim Neustart des Knotens (oder beim Zeitlimit für die Verbindung) und beim erneuten Herstellen der Verbindung zum Client wurde dieselbe Nachricht vom Server zum Zeitpunkt n ausgegeben (wobei n die Anzahl der erneuten Verbindungen war).
Ich habe dieses Problem gelöst, indem ich alle meine Handler aus dem Socket heraus verschoben habe.on ('connect' function () {...}); Funktion außerhalb davon.

Der obige Code macht das, was es braucht.
Dies ist meine vollständige Antwort von der Mailingliste:
https://groups.google.com/forum/?hl=de&fromgroups#!topic/socket_io/X9FRMjCkPco

@xdanx ,

Ja, das scheint auch für mich zu funktionieren: Setzen Sie den Code socket.on ('message') getrennt vom Ereigniscode 'connect'

Aber was ist mit "Verbindung"?
Und was ist mit dem "Socket" -Objekt im Rückruf?

/ edit Nevermind, ich sehe, 'connect' ist auf dem Client. Ich hatte immer noch Probleme mit dem erneuten Verbinden von Spam, wenn ich das nicht getan hatte. Aber das war in 0.9.6

Ich habe anscheinend auch das gleiche Problem ... Ich habe versucht, den Nachrichtencode in separate Blöcke zu verschieben. Ich habe jedoch festgestellt, dass ich ihn nie zusammen hatte.

Gibt es Neuigkeiten zu anderen Workarounds dafür in 0.9.8?

Ich habe das gleiche Problem. Ich habe 0.9.10 installiert. Wie kann man das beheben? :(
Übrigens ist es 1+ Jahre her und noch kein Fix .. :(

BEARBEITEN.

Das Problem scheint verschwunden zu sein, wenn ich nur Jsonp-Polling verwende.
io.set ('transports', ['jsonp-polling']);

Ich habe das gleiche Problem.
Steckdose. [email protected]
Knoten v0.8.8

@semprom Ich denke, die Verwendung von jsonp-polling behebt das Problem, da es möglicherweise nur für Websocket-Verbindungen relevant ist.

Leider hängt meine gesamte Implementierung davon ab, dass das Feedback so schnell wie möglich erfolgt. Daher funktionieren Websockets im Gegensatz zu Abfragen am besten. Da ich die Kontrolle über die Clients habe, die eine Verbindung herstellen, sehe ich keinen Grund außer diesem Problem, zu irgendetwas zu wechseln sonst.

Beachten Sie, dass die mehreren Verbindungen von demselben Client, der erneut eine Verbindung herstellt, dasselbe socket.id . Sie können also Ihre eigene Liste von Socket-IDs verwalten und Duplikate ignorieren, um dieses Problem zu umgehen.

@ KasperTidemann Danke. Es hat dieses Problem gelöst.

@esanai Kein Problem,

Hallo, ich habe das gleiche Problem und habe festgestellt, dass jedes Mal, wenn die Verbindung wieder hergestellt wird, eine neue Client-Socket-ID erstellt wird. Die Lösung ist entweder io.set ('transports', ['jsonp-polling']); oder KasperTidemanns Lösung verwenden?

@ KasperTidemann Meine Güte, Mann, das ist genau die Antwort auf meine Probleme! Siehe dieses Commit: https://github.com/samuelclay/NewsBlur/commit/76cbbd8d8b2a787985bba724dc3562108492b017#L2L3887

Ich kann ein doppeltes Verbindungsereignis nach einem Verbindungsfehler nach Belieben mit diesem einfachen Client- und Servercode in einer einzelnen node.js-Datei reproduzieren:

"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();
});

Irgendeine Arbeit eine Runde oder Korrekturen in Sicht?

Entschuldigung, ich habe dies auch in Ausgabe 474 gepostet.

Ich kann diesen Fehler ziemlich konsistent mit einem iPhone mit iOS 9.3.2 und Chrome Version 50.0.2661.95 und auf Safari für iOS mit Version 1.4.6 von Socket.IO reproduzieren

Ich kann dies nur auf dem Handy reproduzieren und es hängt meine Seite auf der Anfrage an socket.io.

Ich habe eine einfache .on ('connect', Funktion (Socket) {console.log ('Connected');}); und es protokolliert Connected zweimal, wenn der Fehler auftritt, was mich glauben lässt, dass versucht wird, mehrere Socket-Verbindungen gleichzeitig zu öffnen.

screenshot 2016-05-27 13 03 44

Kennt jemand eine Problemumgehung dafür?

Warum wurde diese Ausgabe geschlossen?

Mein Beispielcode vom 14. April 2014 oben erzeugt keine Doppelverbindungsereignisse mehr. Es gibt ein Verbindungsereignis für '/ chat' und eines für den Socket selbst. Welches scheint vernünftig.

Auch im Client gibt es keinen Fehler mehr.

Dies ist mit socket.io 1.4.8 und Knoten 6.3.0.

Dieser Fehler betrifft mich atm.

Wenn die socket_handlers mit Routen platziert werden, werden sie anscheinend mehrmals aufgerufen. Verwenden Sie die Socket-Verbindung in app.js und benötigen Sie Handler innerhalb der Socket-Verbindung. Übergeben Sie den Socket als Parameter. Beachten Sie, dass einige Eigenschaften möglicherweise nicht zusammen mit der Socket-Instanz ausgeliefert werden

@leemlwando bitte öffnen Sie bei Bedarf eine neue Ausgabe.

Ich hatte das gleiche Problem: Ich habe eine manuelle Wiederverbindungsfunktion auf dem Client erstellt und io.destroy () aufgerufen. Innerhalb der Wiederverbindungsfunktion wurde das Problem behoben.

Vielen Dank @leemlwando Dein letzter Kommentar hat mich dazu gebracht, meine Sachen zu lösen.

Ich bekomme immer noch diesen Fehler. Gibt es ein Update?

Ich denke, der einzige wirkliche Fehler hier ist, dass das Internet voller fehlerhafter Beispielcodes ist, in denen socket.on () -Aufrufe in den socket.on-Handler ('connect') eingeschlossen sind. Jedes Mal, wenn der Socket erneut eine Verbindung herstellt, werden neue Instanzen der Handler über die vorhandenen gestapelt. Dies führt bei jedem Ereignis zu mehreren Aufrufen. Tun Sie dies nicht: siehe @KasperTidemanns Antwort vom 25. Juli 2012.

Vielleicht hat DrLexO, außer dem Code, den ich oben vorgestellt habe, das Problem gezeigt. In keinem Socket.on-Handler ('connect') ist socket.on () enthalten.

Nach all den Jahren war ich überrascht, immer noch über diesen Fehler informiert zu werden. Ich habe keine Ahnung, ob es noch etwas ist oder nicht. Muss ich es nochmal versuchen

@ KasperTidemann danke, es hat das Problem tatsächlich gelöst.

Wie können Sie Ihre Ereignis-Listener _outside_ des connect Listeners definieren, wenn Sie keinen Zugriff auf die 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) {
  });
});

Die Leute scheinen vorzuschlagen, dass Event-Listener ( join , add_message und disconnect ) unabhängig leben sollten, _outside_ the connect Listener, aber wie ist das ohne möglich? socket wird definiert?

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) {
});

Gibt es eine andere Möglichkeit, socket zu instanziieren, damit dies möglich ist?

Warum ist das geschlossen? @ Michael-Lynch hat einen gültigen Punkt

Ich würde auch gerne die Antwort auf @ michael-lynchs Punkt wissen.

@ DrLex0 auf dem Beispiel der Website socket.io zeigt sogar Folgendes:

io.on('connection', function(socket){
  socket.on('chat message', function(msg){
    io.emit('chat message', msg);
  });
});
War diese Seite hilfreich?
0 / 5 - 0 Bewertungen