Socket.io: Varios enchufes se abren después de volver a conectar

Creado en 28 jul. 2011  ·  54Comentarios  ·  Fuente: socketio/socket.io

He notado esto tanto en mi aplicación socket.io como en la de otra persona. Cuando ocurre una reconexión, es común que se abra más de un socket dentro de un cliente, lo que nunca debería suceder.

Aquí hay un registro que obtuve de mi propia aplicación de prueba cuando tuve una desconexión / reconexión.

** Desconectar* * Reconexión con retraso 1000 Intentos: 1
** Reconexión con retraso 2000 Intentos: 2* * Conexión con xhr-polling
** Conexión con xhr-polling* * Vuelva a conectar con el tipo de transporte xhr-polling Intentos: 2
** Conectado* * Conectado

Cuando esto sucede, se envían mensajes duplicados, uno para cada toma conectada, aunque solo debería haber una. Firebug confirma que, de hecho, hay dos sockets del cliente conectados. Mi mejor suposición es que esto está en el código del cliente, quizás sin cerrar el primer intento de reconexión.

Por supuesto, la verdadera pregunta podría ser ¿por qué hubo una desconexión en primer lugar?

Socket.IO client bug

Comentario más útil

Investigando esto un poco más, parece que encontré la causa de mis problemas. No es un error , sino una implementación incorrecta del código del lado del cliente de mi parte. facepalm Esto es lo que tenía originalmente:

PROBLEMA:

var socket = io.connect();

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

  console.log('User connected!');

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

    console.log(message);

  });

});

El JavaScript del lado del cliente anterior provocó las múltiples llamadas a console.log () cuando los clientes se volvieron a conectar. Esto es lo que reemplacé lo anterior con:

SOLUCIÓN:

var socket = io.connect();

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

  console.log('User connected!');

});

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

  console.log(message);

});

Ahora, varios mensajes no se envían de un lado a otro cuando los clientes se vuelven a conectar al servidor. ¿Alguien más puede confirmar que un cambio de su código del lado del cliente soluciona el problema?

Todos 54 comentarios

La desconexión se activa porque, técnicamente, el cliente se ha desconectado del servidor. Y se desconecta hasta que se activa de nuevo el evento de reconexión.

Pero el resto es un error.

Creo que esta también es la razón de un error en mi aplicación:

En el lado del servidor, he creado un cursor adaptable en mongodb para que se active cada vez que haya una nueva inserción. Este mensaje luego se envía a través de io.sockets.emit () a todos los conectados.

Pero en lugar de recibir solo un mensaje por evento, recibo múltiples mensajes repetidos en el lado del cliente.

Estoy en una conexión a Internet extremadamente poco confiable, así que supongo que este error también está afectando mi código.

¿Estaban usando expressjs? Tuve este problema con express, lo reescribí sin y funcionó bien.

Express no tendría absolutamente nada que ver con este @mfkp , debe haber estado haciendo algo extraño

De acuerdo con @visionmedia , es un error en socket.io no con Express. Debido a que la implementación de reconexión actual todavía estaba diseñada para 0.6, faltan algunas comprobaciones y limpiezas.

Ah, ya veo. No importa, continúa ;-)

+1 a esto. Problema intermitente en nuestra aplicación de chat donde socket.io abre múltiples conexiones. A continuación, el cliente recibe duplicados de todas las emisiones.

+1. Websockets y cromo. La computadora portátil entra en suspensión -> la aplicación se vuelve a conectar después de la activación -> eventos dobles. Ocurre solo cuando se conecta a un servidor remoto. No se puede reproducir esto localmente, debe haber algún problema de latencia de red / reconexión.

¿Hay alguna solución para deshacerse de las conexiones múltiples después de esto? Por ejemplo, desde el lado del cliente, si hago socket.disconnect (), ¿desconectará todas las conexiones? Como quiero evitar múltiples actualizaciones. ¿Funciona lo siguiente?
socket = io.connect (url)
socket.on ('conectar', función () {
if (multipleConnect) {
socket.disconnect ();
socket.removeAllListeners ('conectar');
io.sockets = {};
socket = io.connect (url);
socket.on ('conectar', functionToConnect);
}
})

Por favor, lea este https://github.com/LearnBoost/socket.io/issues/474#issuecomment -2833227.
Explica por qué ocurre este error y cómo se puede reproducir.

@ 3rd-Eden - ¿Alguna idea de dónde cae esta solución en su lista de tareas pendientes / prioridades? Tengo una aplicación que estoy construyendo y estaba planeando usarla, y me encantaría poder decirle a mi cliente que se volverá a conectar correctamente desde los dispositivos iOS. Se desconecta después de que la aplicación se pone en segundo plano o el dispositivo se pone en reposo.

¿O tiene alguna idea sobre cómo puedo codificar una solución alternativa? He estado trabajando en algunas cosas durante los últimos días, pero en el mejor de los casos siempre parece dejar demasiadas conexiones abiertas y eliminar todos los datos almacenados en sockets. Los datos no son el fin del mundo. Puedo usar el disparador de reconexión del cliente para resolver ese problema, pero las conexiones simultáneas son un poco feas.

¡Gracias!

@cris No estoy seguro de que este sea el mismo error que mencionas. Tengo un ejemplo muy simple del error sin una ralentización en el servidor.

Puedo reproducir claramente este problema mediante:

  1. Implemente un cliente de latidos simple que envíe latidos en intervalos de 1 segundo.
  2. Cuente el número de nuevas conexiones del lado del servidor.
  3. Cuente el número de desconexiones del lado del servidor.
  4. Inicie el servidor y establezca una conexión con un cliente.
  5. Romper la conexión de red entre el cliente y el servidor.
  6. Espere hasta que el servidor se agote y emita un evento de desconexión.
  7. Vuelva a conectar la conexión de red.

Observe que cuando el cliente se vuelve a conectar crea de 2 a 4 conexiones que emiten un evento de "conexión" para cada una. El servidor recibe 2-4 conexiones del cliente y emite un evento de 'conexión' para cada una. El cliente nunca cierra ninguna de las conexiones iniciadas incorrectamente.

Gracias. Realmente creo que este error debería ser una prioridad. Muchas empresas comerciales que no conocen mejor intentan contratar personas para desarrollar contra el marco socket.io, pensando que funciona bien. Por supuesto, socket.io es gratuito, por lo que tal vez estas empresas comerciales deberían comenzar a buscar productos comerciales. Pero, de nuevo, creo que esto realmente debe tener una prioridad muy alta. Este error existe desde 0.7.0 y es fácilmente reproducible.

@davidfooks , @theyak. Arreglé este problema hace mucho tiempo y funciona sin problemas.

Para solucionarlo, debes:

  1. Aplicar este parche: https://github.com/LearnBoost/socket.io-client/pull/342
  2. Deshabilite el protocolo de enlace AJAX (y deje que el protocolo de enlace sea solo a través de JSONP), como se describe en el comentario de la solicitud de extracción.

¿Cómo se desactiva el protocolo de enlace AJAX? Supongo que aún puede usar todos los tipos de conexión, ¿esto solo afectará al apretón de manos?

+1 por favor arregle esto :)

Tuve el mismo problema de conexión múltiple en la reconexión. Creo que este es un problema grave ...
La causa es que se llama al método Socket.connect, pero el indicador de conexión solo se establece en verdadero después de que se completa el protocolo de enlace, en caso de que uno de los temporizadores matbeReconnect (temporizadores que manejan la reconexión) se despierte durante el proceso de enlace, llamarán a Socket. conectarse de nuevo provocando múltiples reconexiones.
Resolví el problema llamando a self.reconnecting al comienzo del método Socket.connect.

¿Alguna posibilidad de fusionar esto?
Este error también está generando un error grave en mi aplicación.

Este error todavía existe. Probé ambos parches. Sin éxito.

+1 Tengo mucho este problema al usar xhr-polling Todavía no probé los parches

+1, yo también tengo este problema con las reconexiones duplicadas.

Siempre que Node.js se reinicia (es decir, cuando se ejecuta a través del supervisor), mis clientes se vuelven a conectar X veces la cantidad de veces que Node.js se ha reiniciado desde el punto en el que los clientes se conectaron inicialmente. El error hace que los eventos se emitan una vez por reconexión desde el lado del cliente; esto no es solo una cuestión de duplicados.

Intenté socket.on('disconnect', function() { socket.disconnect(); }); en el lado del cliente, pero eso no funciona. : /

Investigando esto un poco más, parece que encontré la causa de mis problemas. No es un error , sino una implementación incorrecta del código del lado del cliente de mi parte. facepalm Esto es lo que tenía originalmente:

PROBLEMA:

var socket = io.connect();

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

  console.log('User connected!');

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

    console.log(message);

  });

});

El JavaScript del lado del cliente anterior provocó las múltiples llamadas a console.log () cuando los clientes se volvieron a conectar. Esto es lo que reemplacé lo anterior con:

SOLUCIÓN:

var socket = io.connect();

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

  console.log('User connected!');

});

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

  console.log(message);

});

Ahora, varios mensajes no se envían de un lado a otro cuando los clientes se vuelven a conectar al servidor. ¿Alguien más puede confirmar que un cambio de su código del lado del cliente soluciona el problema?

Hola. Tuve el mismo problema. Cuando estaba reiniciando el nodo (o cuando se agotó el tiempo de espera de la conexión) y el cliente se reconectó, recibía el mismo mensaje emitido por el servidor por n tiempo (donde n era el número de reconexiones).
Resolví esto moviendo todos mis controladores desde el interior del socket.on (función 'conectar' () {...}); función fuera de él.

El código anterior hace lo que sea necesario.
Esta es mi respuesta completa de la lista de correo:
https://groups.google.com/forum/?hl=en&fromgroups#!topic/socket_io/X9FRMjCkPco

@xdanx , genial, gracias por la respuesta.

sí, esto parece funcionar para mí también: poner el código socket.on ('mensaje') separado del código de evento 'conectar'

Pero, ¿qué pasa con "Conexión"?
¿Y qué pasa con el objeto "socket" en la devolución de llamada?

/ edit No importa, veo, 'conectar' está en el cliente. Todavía tenía problemas con la reconexión de spam cuando no lo había hecho. Pero eso fue en 0.9.6

Parece que también tengo el mismo problema ... Intenté la solución anterior de mover el código del mensaje a bloques separados ... pero noté que nunca lo tenía junto.

¿Alguna noticia sobre otras soluciones para esto en 0.9.8?

Tengo el mismo problema. Tengo 0.9.10 instalado. Cualquier forma de arreglar esto? :(
por cierto, ha pasado más de 1 año y aún no hay solución .. :(

EDITAR.

El problema parece desaparecer cuando solo estoy usando jsonp-polling.
io.set ('transportes', ['jsonp-polling']);

Tengo el mismo problema.
enchufe. [email protected]
nodo v0.8.8

@semprom Creo que el uso de jsonp-polling lo soluciona porque podría ser relacionado solo con las conexiones websocket.

Desafortunadamente para mí, toda mi implementación se basa en que la retroalimentación sea lo más rápida posible, por lo que los websockets en lugar del sondeo funcionan mejor. más.

Tenga en cuenta que las múltiples conexiones del mismo cliente que se reconectan tienen el mismo socket.id . Por lo tanto, puede mantener su propia lista de ID de socket e ignorar los duplicados para solucionar este problema.

@KasperTidemann Gracias. Resolvió este problema.

@esanai No hay problema, ¡me alegro de que haya funcionado!

Hola, tengo el mismo problema y noté que cada vez que se vuelve a conectar la conexión, se crea una nueva identificación de socket de cliente. La solución es usar io.set ('transportes', ['jsonp-polling']); o usa la solución de KasperTidemann?

@KasperTidemann ¡Dios mío, hombre, esa es exactamente la respuesta a mis problemas! Vea este compromiso: https://github.com/samuelclay/NewsBlur/commit/76cbbd8d8b2a787985bba724dc3562108492b017#L2L3887

Puedo reproducir un evento de doble conexión después de un error de conexión a voluntad con este simple código de cliente y servidor en un solo archivo 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();
});

¿Algún trabajo, rondas o arreglos a la vista?

Lo siento, también publiqué esto en el número 474.

Puedo reproducir este error de manera bastante consistente usando un iPhone con iOS 9.3.2 y Chrome Versión 50.0.2661.95 y en Safari para iOS con la versión 1.4.6 de Socket.IO

Solo puedo reproducir esto en un dispositivo móvil y cuelga mi página en la solicitud de socket.io.

Tengo un simple .on ('conectar', función (enchufe) {consola.log ('Conectado');}); y registra Conectado dos veces cuando ocurre el error, lo que me lleva a creer que está intentando abrir múltiples conexiones de socket al mismo tiempo.

screenshot 2016-05-27 13 03 44

¿Sabe alguien una solución para esto?

¿Por qué se cerró este problema?

Mi código de ejemplo del 14 de abril de 2014 anterior ya no produce eventos de doble conexión. Hay un evento de conexión para '/ chat' y uno para el propio socket. Lo que parece razonable.

Tampoco hay ningún error incluso en el cliente.

Esto es con socket.io 1.4.8 y nodo 6.3.0.

Este error me está afectando en el cajero automático.

Aparentemente, cuando los socket_handlers se colocan dentro de las rutas, se llaman varias veces. Use la conexión de socket dentro de app.js y requiera controladores dentro de la conexión de socket, pase el socket como parámetro. Tenga en cuenta que es posible que algunas propiedades no se envíen junto con la instancia de socket

@leemlwando , abre un nuevo problema si es necesario.

Tuve el mismo problema que hice fue hacer una función de reconexión manual en el cliente y llamar a io.destroy (); dentro de la función de reconexión, esto solucionó el problema.

Muchas gracias @leemlwando Tu último comentario hizo que resolviera mis cosas.

Sigo recibiendo este error, ¿hay alguna actualización?

Creo que el único error real aquí es que Internet está lleno de código de ejemplo incorrecto donde las llamadas socket.on () están envueltas dentro del controlador socket.on ('connect'). Cada vez que el socket se vuelve a conectar, se apilan nuevas instancias de los controladores sobre las existentes y esto da como resultado múltiples llamadas en cada evento. No hagas esto: consulta la respuesta de @KasperTidemann del 25 de julio de 2012.

Quizás DrLexO, excepto que el código que presenté anteriormente demostró el problema. No tiene socket.on () envuelto dentro de ningún controlador socket.on ('conectar').

Después de todos estos años, me sorprendió que todavía me notificaran sobre este error. No tengo ni idea de si es una cosa todavía o no. ¿Tengo que intentarlo de nuevo?

@KasperTidemann gracias, en realidad resolvió el problema.

¿Cómo puede definir sus oyentes de eventos _fuera_ del oyente connect cuando no tiene acceso al 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) {
  });
});

La gente parece estar sugiriendo que los oyentes de eventos ( join , add_message y disconnect ) deben vivir de forma independiente, _fuera_ del oyente connect , pero ¿cómo es posible sin socket siendo definido?

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 una forma diferente de instanciar socket para que esto sea posible?

¿Por qué esta cerrado? @ michael-lynch tiene un punto válido

También me gustaría saber la respuesta al punto de @ michael-lynch.

@ DrLex0 en el ejemplo del sitio web socket.io, incluso muestra hacer lo siguiente:

io.on('connection', function(socket){
  socket.on('chat message', function(msg){
    io.emit('chat message', msg);
  });
});
¿Fue útil esta página
0 / 5 - 0 calificaciones

Temas relacionados

kootoopas picture kootoopas  ·  4Comentarios

karmac2015 picture karmac2015  ·  3Comentarios

MyMomSaysIAmSpecial picture MyMomSaysIAmSpecial  ·  4Comentarios

dmuth picture dmuth  ·  3Comentarios

thebinarypenguin picture thebinarypenguin  ·  4Comentarios