Socket.io: Conexión doble

Creado en 23 ago. 2011  ¬∑  42Comentarios  ¬∑  Fuente: socketio/socket.io

de alguna manera ocurre una doble conexión con los clientes (lo que significa que todos los controladores son llamados dos veces), no pude reproducir la situación por mi cuenta, pero sigo recibiendo informes de errores, el comportamiento es exactamente el mismo si llama a socket.socket.connect () ya conectado socket. (probado en websocket y flashsocket)

Socket.IO client bug

Comentario m√°s √ļtil

Todavía me encuentro con este problema siguiendo el ejemplo básico.

EDITAR: Encontré una solución, aunque no estoy seguro de que sea exactamente adecuada. Básicamente, todo lo que requiere es usar

io.once('connection', ...)

en vez de

io.on('connection', ...)

Todos 42 comentarios

como truco rápido puede usar "forzar nueva conexión": configuración falsa

También observé este error en nuestra aplicación.
Reproduce fue el siguiente. En FF con conexi√≥n websocket, ocurri√≥ alg√ļn error. Luego, uno tras otros 3 eventos de reconexi√≥n se hab√≠an generado. Despu√©s de esto, se establecieron 3 nuevas conexiones y el navegador recibi√≥ 3 mensajes en lugar de uno.

¬ŅQuiz√°s alg√ļn error en la l√≥gica de reconexi√≥n? Algo, que genera varias reconexiones en lugar de una.

He visto problemas en navegadores m√°s antiguos que no admiten websockets (por ejemplo, FF 3.6) donde la inicializaci√≥n de socket.io en el evento dom ready ("$ ()" en jQuery) causa m√ļltiples conexiones mientras se inicializa en la ventana posterior. el evento no lo hace. Descubr√≠ que este problema en particular se puede reproducir de manera consistente. No estoy seguro de si es lo mismo que est√° viendo, pero los s√≠ntomas se ven muy similares.

El mismo problema aqu√≠ tambi√©n. El problema es que si el servidor se bloquea por cualquier motivo y luego se vuelve a encender, la reconexi√≥n da como resultado n + 1 respuestas cada vez. as√≠ que si tenemos, digamos, 3 fallas del servidor, tendremos 4 respuestas en cada servidor emitido. Actualizar la p√°gina resuelve el problema. ¬ŅAlguien ha encontrado una soluci√≥n para esto [aunque sea temporal?]

Puede que esta no sea una solución permanente, pero reorganicé mi código para que cada evento se vincule de forma independiente y el problema de duplicación parece haberse resuelto en la reconexión automática

me.socket.on('connect', function () {
});

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

});

me.socket.on('disconnect', function() {

});

Después de una semana de depuración a través del volcado de Wireshark capturado, me las arreglé para encontrar el motivo y reproducir este error.

En resumen, la lógica de reconexión es muy frágil. Depende de muchos temporizadores que pueden funcionar en paralelo y conduce a varias reconexiones. Esta línea https://github.com/LearnBoost/socket.io-client/blob/master/lib/socket.js#L511 es la razón principal de este error.

Ahora reproducción completa:

  1. Conéctese con el cliente al servidor.
  2. Ponga código lento en su servidor (deberíamos suspender el mainloop de node.js durante 4-8 segundos) a través de factorial:
    función fibo (n) {
    si (n <2) devuelve 1;
    devuelve fibo (n-2) + fibo (n-1);
    }
    Ponlo en la sección de autenticación. Esto debería llamarse en apretón de manos:
    io.set ('autorización', función (datos, aceptar) {
    console.info ("Fibo ::" + fibo (41));
    Debería experimentar en su consola de nodo, para encontrar fibo (N), que
    bloquear√° el bucle principal durante 4-8 segundos.
  3. Ahora, debe reiniciar r√°pidamente su servidor.
    Se aplicará un código lento para la conexión.
    Se debe notificar al cliente que no se apretó la mano
    Y ahora intenta volver a conectarse.
    En la consola, verá varios intentos de reconexión (si activa el inicio de sesión en las devoluciones de llamada "reconectar / reconectar").
    Después de nuestro truco de desaceleración, se repetirá para siempre.

En la vida real, esto se reproducía a través de la ralentización de la respuesta del servidor al menos durante varios segundos.
Esto puede ocurrir cuando node.js est√° bajo una carga pesada y responde con cierta demora.
O alguna ralentización de la red también puede conducir a tal comportamiento.
También se puede reproducir después de reiniciar el servidor.

Esta línea (socket.js, 511):
self.reconnectionTimer = setTimeout (tal vezReconnect, self.reconnectionDelay);

programa el evento después de la llamada de conexión. Y si la respuesta de conexión se retrasa al menos un segundo, se activa y se coloca una nueva reconexión en la cola. Después de 2 segundos agrega otro y así uno.

Hice una solución, pero no está probado y no parece muy sólido. Problema principal: cómo razonar sobre qué devolución de llamada / temporizador se puede ejecutar al mismo tiempo para la función MaybeReconnect.
Esta línea: https://github.com/LearnBoost/socket.io-client/blob/master/lib/socket.js#L490 también puede conducir a una conexión duplicada.

El cliente Socket.io puede ser mucho más simple de razonar, si se refactoriza para usar alguna máquina de estado. Actualmente, el estado se distribuye a través de diferentes banderas (conectado, conectando, reconectando, etc.). Y en muchas funciones vi guardias como "if (! Self.reconnecting)" y muchos otros.
La máquina de estados puede simplificar esta lógica para tener un conjunto de estados y eventos. Y los temporizadores solo se pueden usar para disparar eventos. Si este evento alcanza un estado incorrecto, state-machine puede simplemente ignorar este evento y no molestarse.

No he encontrado un buen STM para JS, pero este de Ruby se puede portar f√°cilmente a JS: https://github.com/geekq/workflow

Definitivamente +1 para reparar este problema. He estado trabajando para tratar de encontrar una soluci√≥n para este problema sin modificar socket.io o socket.io-client directamente, pero desafortunadamente el √ļnico m√©todo que he encontrado de manera confiable es simplemente deshabilitar la reconexi√≥n. Lo que definitivamente no es una buena soluci√≥n, especialmente con el mayor uso de dispositivos m√≥viles, la reconexi√≥n es un requisito enorme.

¬ŅAlguien tiene alguna idea de c√≥mo cae esto en la lista de prioridades de los desarrolladores?

¬°Ah! Parece que este problema se ha asignado a 3rd-Eden desde el problema: https://github.com/LearnBoost/socket.io/issues/430

Hice una corrección para un cliente y envié una solicitud de extracción. Funciona bien en 0.8.4 y puede funcionar bien en otras versiones. Pero requiere deshabilitar en las fuentes la capacidad de usar AJAX (o CORS) para el protocolo de enlace. Vea esto: https://github.com/LearnBoost/socket.io-client/pull/342 para más detalles.

Perd√≥n por revivir un problema tan antiguo. Creo que estoy usando la √ļltima versi√≥n de socket.io (o al menos, hice npm install socket.io). Este problema todav√≠a me ocurre, soy relativamente nuevo en socket.io y node.js en su conjunto. Tambi√©n he tenido problemas en los que a veces la primera conexi√≥n (de las dos que solo he tenido en un momento determinado) tiene un error de lectura. Si estoy en lo cierto al decir cris, su soluci√≥n se comprometi√≥, por lo que ya no deber√≠a suceder, pero a√ļn as√≠, a menos que me haya perdido un factor importante.

Editar -

Parece que cris bifurcó socket.io e hizo una corrección en eso y la corrección no se comprometió con el socket.io original.

@JTallis Tuve el mismo problema que @gdiz y su sugerencia funcionó bien. Si tu problema es similar, te sugiero que lo pruebes y nos digas cómo funciona.

Tambi√©n tengo este problema con 0.9.16, que creo que es la versi√≥n m√°s actual. ¬ŅC√≥mo funciona gdiz para evitar que esto ocurra? No lo entend√≠ completamente.

Dios mío ... paso varias horas para averiguar qué está mal con mi aplicación y por qué los mensajes entre el servidor y el cliente se duplicaron en masa después de que la conexión se perdió y se renovó ...

usando 0.9.16 puedo confirmar este problema

Puedo obtener un evento de doble conexión a voluntad con el siguiente código de cliente y servidor en el mismo archivo 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');
    });

    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('error', function () {
    console.log("Client: error");
    socket.socket.reconnect();
});

Un par de cosas extra√Īas:

1) Si cambio la conexión de espacio de nombres a una normal eliminando "/ chat" de la URL, solo hay un evento de conexión.

2) Si inicio el servidor inmediatamente, cambio el tiempo de setInterval a cero, no hay error de conexión inicial y solo un evento de conexión.

¬ŅAlguna soluci√≥n o soluci√≥n para esto?

Tener el mismo problema. Si el servidor socket.io se reinicia inesperadamente, el cliente se vuelve a conectar dos veces, por lo que cada mensaje es procesado dos veces por el cliente. Realmente arruina mis cuentas por parte del cliente.

Tengo el mismo problema con la versión 1.0.0-pre2. Tengo dos "400 solicitudes incorrectas" cuando reafirmo socket.io.

¡Examinaré esto hoy!

¡Examinaré esto hoy!

¬°No lo dudes si necesitas m√°s detalles, registros o pantallas! No todas las veces.

en el cliente socket.io.js en 1.0.6 en la línea 2755:

Request.prototype.create = function (isBinary, supportsBinary) {
var xhr = this.xhr = new XMLHttpRequest ({agente: this.agent, xdomain: this.xd});
...
}

Creo que es una buena idea establecer:
xhr.timeout = instancia de Manager._timeout - 10 ms
De esta manera, evita la creaci√≥n de m√ļltiples sockets de cliente en el lado del cliente.
En el lado del servidor, varios sockets se agotar√°n.

El ejemplo básico de socket.io "Getting Started" (http://socket.io/get-started/chat/) tiene este problema de conexión de doble socket.

Uno de los siguientes (en orden creciente de probabilidad) da como resultado la conexi√≥n de doble socket desde una sola conexi√≥n de pesta√Īa del navegador:
a) Al conectarse a localhost: 3000, desde la primera pesta√Īa del navegador
b) Al conectarse a localhost: 3000, desde una segunda pesta√Īa del navegador
c) Mantener abierta la consola del navegador antes de conectarse a (localhost: 3000)

Observaciones adicionales:

 io.on('connection', function(socket){
    console.log('a user connected: ' + socket.id);
    socket.on('disconnect', function(){
       console.log('a user disconnected');
       console.log(socket.nickname + ' has disconnected from the chat.');
    });
});
  1. Hay dos socket.id distintos que emanan de una sola solicitud de pesta√Īa del navegador.
  2. La conexión de socket "duplicada" se desconecta, en aproximadamente un minuto con el archivo console.log de "undefined se ha desconectado del chat".
  3. Usando express generator 4.2 (usando Morgan) y luego implementando el ejemplo "Getting Started", las "buenas" conexiones del navegador dan como resultado registros rápidos de una sola línea, por ejemplo, "GET / 304 1ms". Pero siempre que exista esta conexión de socket "doble", hay dos registros rápidos, "GET / 304 1ms" Y "GET / 200 3ms - 386b"

Estoy usando Mac, Chrome, Express 4.2 y el √ļltimo socket.io.

Existe una diferencia temporal entre la creación de los dos registros. El primer registro se activa cuando Chrome completa automáticamente mi "lo" a " localhost: 3000 " y el segundo registro se activa cuando presiono el botón Enter.

Tenía un mensaje de registro de la consola "X usuarios conectados" y era muy molesto cuando mi propio navegador activaba 2 o 3 avisos de conexión de usuario.

Ahora, debo confesar que mi solución al problema fue comentar la línea console.log. Pero sigan con el buen trabajo, muchachos.

Sigo viendo este problema en la √ļltima versi√≥n. ¬ŅAlguna actualizaci√≥n sobre esto?

También veo este problema con 1.0

No puedo reproducirlo en absoluto. ¬ŅAlguien puede publicar un ejemplo completo?

El viernes 14 de noviembre de 2014 a las 2:44:50 a. M. Rex Pechler [email protected]
escribió:

También veo este problema con 1.0

-
Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/Automattic/socket.io/issues/474#issuecomment -62934229
.

Ver√© si puedo preparar un ejemplo simple ma√Īana.

Podría reproducirlo. Estoy usando socket.io 1.3.5 y express 4.12.4.

Mi aplicación express se encuentra en 127.0.0.1:3000 y abro mi navegador y escribo esa dirección IP y socket.io abre solo un websocket.

Tengo un dominio como abc.com y lo reenvío a 127.0.0.1. Abro abc.com en mi navegador y en el archivo index.html está la línea;

<script>
        var socket = io('http://localhost:3000/mysql');

        socket.on('processlist', function (data){
            console.log(data);
        });
</script>

esto abre 2 websockets.

Todavía no he probado nginx con proxy. Te lo haré saber tan pronto como lo intente.

screen shot 2015-05-29 at 23 53 29

Todavía encuentro este problema. Para mí, sucedió en el reinicio del servidor: estaba adjuntando mis controladores de eventos socket.on ('mensaje') cuando se disparó el evento de conexión inicial del servidor, y si el servidor se reiniciaba mientras el cliente estaba abierto, ese evento se activaba varias veces (más tiempo el más tiempo el cliente había estado esperando el reinicio del servidor).

Mi solución por ahora ha sido 'eliminar el rebote' del evento de socket adjunto para que solo ocurra en la primera conexión del servidor, así:

client.socketEventsAttached = false;

socket.on('connect',function(){
     if (!client.socketEventsAttached){
          attachSocketEvents();
     }
});

También puede colocar sus oyentes de eventos de mensajes fuera del oyente socket.on ('connect') como sugirió @gdiz . Acabo de tener algunos problemas con los eventos de socket que se activan antes de que el servidor o el cliente estén listos para ellos.

@bbcollinsworth ¬Ņcu√°l es el objeto del cliente?

Todavía encuentro este problema con socketio nuevo y un ejemplo básico.

Todavía me encuentro con este problema siguiendo el ejemplo básico.

EDITAR: Encontré una solución, aunque no estoy seguro de que sea exactamente adecuada. Básicamente, todo lo que requiere es usar

io.once('connection', ...)

en vez de

io.on('connection', ...)

@brandonraphael, ¬Ņ podr√≠a proporcionar un ejemplo que reproduzca su problema (basado en https://github.com/darrachequesne/socket.io-fiddle, por ejemplo) y abrir un nuevo problema?

Cualquier actualización, esto todavía está sucediendo y creando problemas en la aplicación

Estos son los registros:
0 | Servidor Api | ¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°Conectado!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! DKap3hUYFSpKBRr7AFgc 4351 2018-12-26 10:58:25
0 | Servidor Api | ¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°¬°Conectado!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! VS98DBFVTNF6ifzmAFgd 4351 2018-12-26 10:58:25

4351 es la identificaci√≥n del usuario y el n√ļmero de conexiones tampoco es est√°tico como 2 en el caso del usuario 4351.
Otro registro muestra 6 conexiones al mismo tiempo para el mismo usuario.

Adem√°s, he comprobado estos dos ID de socket en el servidor y se muestran v√°lidos. Pero la interfaz solo puede escuchar uno de ellos, que siempre es el primer ID de socket.

Cualquier ayuda sería genial.
Gracias por adelantado.

Todavía me encuentro con este problema siguiendo el ejemplo básico.

EDITAR: Encontré una solución, aunque no estoy seguro de que sea exactamente adecuada. Básicamente, todo lo que requiere es usar

io.once('connection', ...)

en vez de

io.on('connection', ...)

gracias por esto

El problema se resolvi√≥ despu√©s de cambiar la versi√≥n utilizada en el cliente. Otra soluci√≥n ser√≠a usar habitaciones en lugar de una √ļnica identificaci√≥n de socket. Descubr√≠ que cada ID de socket es en s√≠ mismo una habitaci√≥n, solo la parte que se iba a cambiar era el nuevo c√≥digo de conexi√≥n de poner cada ID de socket en la habitaci√≥n del usuario.
Considere que un usuario slug es User1, luego se creó una sala User1 y cada nueva conexión de socket a través de slug User1 se colocó dentro de la sala User1.

Estaba teniendo el mismo problema y me estaba volviendo loco. Definitivamente NO estaba volviendo a registrar los oyentes de eventos en el cliente tampoco. En mi configuraci√≥n, tengo un servidor nodejs que aloja el punto final socketio y tambi√©n tengo otro servidor nodejs que act√ļa como mi cliente socketio. El truco consist√≠a en conectar el lado del cliente con el transporte websocket y usar forceNode . Ex

// client side
const socket = io('<url>', {
  transports: ['websocket'],
  forceNode: true,
});

Creo que estoy teniendo el mismo problema. Estoy construyendo una sala de chat y cuando alguien se une a la sala, emito un "se ha unido a la sala "mensaje a la sala.

Todo funciona muy bien, pero si salgo de la habitación y luego entro por segunda vez, el mensaje de introducción se emite _dos veces_. Si salgo de la habitación de nuevo y vuelvo a entrar en ella por tercera vez, el mensaje de introducción se emite tres veces, y así sucesivamente. Cada _reconexión_ a la _misma_ sala da como resultado un mensaje de introducción duplicado. Sin embargo, si entro en una habitación _diferente_, solo veo el mensaje de introducción una vez.

Usar io.once('connection', ...) no funcionó para mí. De hecho, todos mis eventos dejaron de funcionar.

El uso del método "antirrebote" tampoco funcionó. Una vez más, ninguno de mis eventos se registró.

Por √ļltimo, el uso del lado del cliente de la opci√≥n forceNode: true tampoco funcion√≥.

Estoy usando 2.2.0 tanto en el servidor como en el cliente. ¬ŅHay algo que me est√© perdiendo?

Me preguntaba sobre el mismo problema, pero en √ļltima instancia, decirle al cliente que se conecte solo once ayud√≥.

Aquí está mi configuración para el cliente:

var socket = io.connect("http://localhost:3000/test", 
    { upgrade: false, transports: ['websocket'], reconnection: true, forceNew: false});
socket.once('connect', socketConn => {
    socket.on('message', data => {
        console.log(data);
    });
}); 

El cliente simplemente se registrará once para el evento connect , por lo que cualquier otro evento dentro de él se registraría una vez. Ahora, si el servidor falla, el cliente simplemente intentará volver a conectarse y no intentará crear una nueva conexión. Tan pronto como reciba la respuesta del servidor, comenzará a procesar los mensajes.

Por lo tanto, io.once debe configurarse en el lado del cliente, no en el lado del servidor.

Estoy usando la versión del cliente 2.1. Encuentro que es muy fácil activarlo en mi entorno de desarrollo. Cada vez que mi servidor de nodo se reinicia (por ejemplo, usando nodemon), el cliente siempre activa varios eventos de reconexión y luego se conecta incluso. Pero no puedo averiguar la causa raíz

Estoy usando la versión del cliente 2.1. Encuentro que es muy fácil activarlo en mi entorno de desarrollo. Cada vez que mi servidor de nodo se reinicia (por ejemplo, usando nodemon), el cliente siempre activa varios eventos de reconexión y luego se conecta incluso. Pero no puedo averiguar la causa raíz

Estaba teniendo el mismo problema que también con el propio nodemon. pero finalmente, decirle al cliente que se conectara solo once ayudó.
Prueba el código de mi respuesta justo arriba. Me ayudó y cada vez que se reinicia el servidor, los clientes obtienen nuevas conexiones.

Mi problema era simple

Ten√≠a la misma aplicaci√≥n del lado del cliente abierta en 2 pesta√Īas. Ups

Yo también tuve el mismo problema. Sin embargo, para mí, puse por error mis controladores del lado del cliente dentro de la función de devolución socket.on('connection', cb) llamada

Aquí hay un fragmento para demostrar:

client.js (en node.js)

const client = require('socket.io-client');
const socket = client('my_endpoint', {
  transports: [ 'websockets' ]
});

socket.on('connect', () => {
  console.log('connected');
  socket.on('myEvent', (message) => {
    console.log(`message: ${message}`);
  });
});

Cuando ocurriera una desconexión y reconexión, llamaría a socket.on('connect', cb) nuevamente, y el controlador myEvent registraría un segundo controlador con el mismo nombre. Entonces, cuando el servidor emitió myEvent nuevamente, tendría dos registros de consola del mismo mensaje.

Para resolverlo, tuve que poner mis otros controladores fuera del controlador connect .

const client = require('socket.io-client');
const socket = client('my_endpoint', {
  transports: [ 'websockets' ]
});

socket.on('connect', () => {
  console.log('connected');
});

socket.on('myEvent', (message) => {
  console.log(`message: ${message}`);
});

Creo que mi confusión vino de cómo los documentos muestran que el lado del servidor coloca eventos socket.on dentro del evento connect . Eso depende de mí por no leer los documentos con más atención, pero pensé que pondría esto aquí en caso de que alguien más cometa el mismo error.

Además, aunque vi este problema en node.js específicamente, estoy seguro de que esto también sería un problema en el navegador.

¬ŅFue √ļtil esta p√°gina
0 / 5 - 0 calificaciones

Temas relacionados

theyak picture theyak  ¬∑  54Comentarios

hwalyonglance picture hwalyonglance  ¬∑  6Comentarios

edmellum picture edmellum  ¬∑  130Comentarios

betooo0997 picture betooo0997  ¬∑  5Comentarios

MickL picture MickL  ¬∑  12Comentarios