Socket.io: Duplicate events

Created on 17 Aug 2012  ยท  28Comments  ยท  Source: socketio/socket.io

Here I create primitive example of server with socket.io with such stuff:

  • socket.io > 0.9.9
โ”œโ”€โ”ฌ [email protected]
โ”‚ โ”œโ”€โ”€ [email protected]
โ”‚ โ”œโ”€โ”ฌ [email protected]
โ”‚ โ”‚ โ””โ”€โ”€ [email protected]
โ”‚ โ””โ”€โ”ฌ [email protected]
โ”‚   โ”œโ”€โ”ฌ [email protected]
โ”‚   โ”‚ โ””โ”€โ”€ [email protected]
โ”‚   โ”œโ”€โ”€ [email protected]
โ”‚   โ”œโ”€โ”ฌ [email protected]
โ”‚   โ”‚ โ”œโ”€โ”€ [email protected]
โ”‚   โ”‚ โ”œโ”€โ”€ [email protected]
โ”‚   โ”‚ โ””โ”€โ”€ [email protected]
โ”‚   โ””โ”€โ”€ [email protected]
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ—

_on x86_64 Linux_:

Distributor ID: Ubuntu
Description: Ubuntu 12.04.1 LTS
Release: 12.04
Codename: precise
Kernel: 3.2.0-29-generic
GCC version: 4.6 (x86_64-linux-gnu)

var io = require('socket.io').listen(1717);

io.sockets.on('connection', function (socket) {
  socket.on('ping', function (data){
      console.log(data);
  });

  socket.on('message', function(data){
      console.log(data);
  });
});

And PHP-client like this:

#!/usr/bin/php -q

<?php
error_reporting(E_ALL);
require(dirname(__FILE__).'ElephantIO/Client.php');

$elephant = new ElephantIO\Client('http://localhost:1717');
$elephant->init(false);

$elephant->emit('ping', array('test' => 'Hello World!'), '');
// $elephant->send(ElephantIO\Client::TYPE_MESSAGE, null, null, 'Hello World!');

Here is the log of that server:

   info  - socket.io started
   debug - client authorized
   info  - handshake authorized KAZbMECxcHQBIgTXynHr
   debug - setting request GET /socket.io/1/websocket/KAZbMECxcHQBIgTXynHr
   debug - set heartbeat interval for client KAZbMECxcHQBIgTXynHr
   debug - client authorized for 
   debug - websocket writing 1::
   debug - websocket received data packet 1:::
   debug - websocket writing 1::
   debug - websocket received data packet 3:::Hello World!
Hello World! 
Hello World!

So, every time php-client sends one message or emits event, it's duplicated on the server side :(

Most helpful comment

Just ran into this issue as well.

Originally, I was attaching listeners on the client like this:

socket.on('connect', () => {
    socket
        .emit('sendAuthCredentials', { ... })
        .on('user joined', () => { ... })
        .on('user left', () => { ... })
})

But @EduardJS explains it very well:

What you need here is to make sure you attach the events only once, no matter how many re-connections you have

My solution was to take the listeners out of the connect callback, and only leave my auth check (which I do want to run on every connection attempt):

socket.on('connect', () => {
    socket.emit('sendAuthCredentials', { ... })
})

socket
    .on('user joined', () => { ... })
    .on('user left', () => { ... })

All 28 comments

I have the same issue, but I'm listening to a file on the server instead of waiting for PHP to send the notification. Could you find anything to resolve your issue? Here is mine: https://github.com/LearnBoost/socket.io/issues/999

I think I might have a similar issue as well.. although mine seems to stem from restarting the socket.io server.

I use a fairly convoluted system between redis subscribes and php scripts to propogate events and changes down to the clients. It seems that each time the socket.io server is restarted and the clients reconnect the clients get an extra duplication of all events.

In my case however I am using the redis backend, so it might be a duplicate subscription issue.

I also have this issue. Like SiasMey, I use a redis pubsub subscription and php scripts. It is not a duplicate subscription issue (because even when using redis-cli to publish a single event to a single subscriber, the node.js server generates two emits).

By duplicate subscription I meant that the socket.io server might be subscribed to the same channel twice, so sending a single publish would generate two events in node.

I did however test the socket.io server without the redis backend as well and it still generated the duplicate events, so it doesent seem to be related to the redis backend (by that I mean the socket.io redis-store backend).

There seem to be quite a few issues linked to similar symptoms .. the duplicate connection issue #430 (too much http recently) seems most likely to be the root cause to me, but im new at this kind of hacking :-).

Having the same issue. After restarting socket.io server side, there are some duplicates of events going on. It feels like they sit in a buffer or something and then fired up when reconnect happens.

It seems, that explanation of problem is in core of TCP transfers.

Suppose websocket transfer used. Between server side is down and up again after restart, client side try (websocket) reconnect 3 times. This TCP connection opening packets lives in TCP stack on server side independently (all 3) with cca 30 seconds in TIME_WAIT state (trying reconnect).

If server side wake up during this 30 seconds, ALL sockets waiting for reconnect are accepted as CONNECT requests.

This situation is in any case, when server side cannot answer immediately - huge work, lot of connections, off/on . (??browser_internally_defined_max_waiting_time_to_answer_then_try_reconnect = 3,4 secs_??) .

I thing that only solution is strongly identify REQUESTER_ID + CHANNEL_ID (to allow one requester to have multiple single-socket communication channels) and discard (close socket) repeated requests to connect.

BTW: there are not only duplicates ... repeatingly stop and start server it can be possible, that all free sockets on server are occupied.

I feel it as VERY BIG PROBLEM

@supipd - That doesn't appear to be the case with me. The duplication issue is consistent regardless of

  • number of connections
  • wait time between server restarts
  • load on server

I tested this on my local system with very little else running

I thing that only solution is strongly identify REQUESTER_ID + CHANNEL_ID

Are you referring to identification by socket id? Then you can set force new connection to true. That, however, does not solve the issue either.

The connections in the pool are duplicated each time a client reconnects.

Client connects - 1 connection
Server down, then back up...
Client reconnects - 2 connections
Server down, then back up...
Client reconnects - 4 connections
Server down, then back up...
Client reconnects - 8 connections
Server down, then back up...
....... etc

Any updates on this issue, as I encounter the same problem but only when sending a push notification from Elephant.IO, if I use javascript it works just fine.

I got the same issue even using Javascript

I have the same problem on linux, when using PHP to submit one event, its been fired twice ... the issue is closed without any further explanation or solution, why ?

Make sure you check the debug output, see http://socket.io/docs/logging-and-debugging/ This could rule out that it's in your own code.

I run very basic example from docs, no fancy code (yet), and I am experiencing the double events being fired. I will try to log/debug the output and will see whats going on.

EDIT : the event is being fired twice from the server, its not client side issue :(

I have this issue too and I am using the code from the website's example.

Was this ever fixed? I think I'm seeing the same issue with a very simple ping-pong script.

Same issue here using Flask-SocketIO 1.1 on server

Just can't believe since August 2012 this issue wasn't properly addressed and people still continue reporting it. The splendors and miseries of open source. ๐Ÿ˜ฎ

You guys found a fix for this issue since I see it as closed ? I'm still experiencing the same issue... with a simple ExpressJS / Socket.io app. I connect the one user, broadcasting it to other users,
restarting the server, connecting the same user, the broadcast is being received twice on the second restart. Three times after the third restart, and so on.

http://i.imgur.com/TUJr3yf.png

I have 2 clients connected with some debugging and I'm broadcasting two events uppon connection and one on disconnect.

Upon connection:
1 - broadcast to all users ( aside the current one ) the "member_joined" event.

  1. broadcast to socket.id ( current user ) the "member_list" event so I can show what users are already online.

Upon disconnect:

  1. broadcast to all users aside current one, the member_left event so others are aware of it.

Now that I have two clients connected, the events are triggered as many times as the server has been restarted. Look at that image.

My thought was .. to try and disconnect the client from all rooms or something upon server being restarted. Is that possible ?

Problem is about where you call you message event " socket.on('message') " must not be inside connection scope in your client js file .

io.sockets.on('connection', function (socket) { });

--> This is out of the scope ....
socket.on('message', function(data){ console.log(data); });

@islam9 You have no idea what you're talking about.

What he wrote in his example is perfectly correct. I have already fixed the problem and this is not related by far with socket.io , nor nodejs, that's why they cannot / wont fix it.

When you attach event handlers to a socket there is no way in hell you're going to get that socket object if you are not inside the connection like this.

io.on('connection, function( socket ){ });

Think of that socket param as being the object in which the client's socket is saved. Each of them will be one of those sockets to which you'll have to attach some events in order to listen to them disconnecting, pinging, etc.

The problem is in the client itself, and it's related to your clients reconnecting to your socket server.
Therefore it has nothing to do with socket.io. When the server is not reachable for any reason, the events your client attaches upon connection will be listened to again ( and again, as many times your socket.io reconnects successfully ).

Therefore, my fix, since I am working with simple javascript as my own "client" interface, I'm checking if there is already a handler like the one I'm trying to attach, before attaching it upon reconnection, and since reconnection implies the connect event to be triggered again, your client will attach two or more callbacks to the same event.

image

Check out my issue it has more images to explain https://github.com/socketio/socket.io/issues/2529

@EduardJS I mentioned that its the client file , and not related to the nodeJS ,
Also , am am indicating that issue is regarding duplicate msg not connection .

@EduardJS why not just use this.socket.once?

@JCMais 'socket.once' will remove the event after it has been fired. Therefore it is not usable.

What you need here is to make sure you attach the events only once, no matter how many re-connections you have.
You do not want to remove them after they fire first time ( which is what .once does ) as they can fire multiple times. Think of receiving messages for that matter. You want to receive all messages, not just one and then unbind the event.

@EduardJS yes, I saw my mistake on using .once yesterday, forgot to edit my comment.

Basically it's because most (myself included) people add all events inside the connection callback, which causes that behavior.

Just ran into this issue as well.

Originally, I was attaching listeners on the client like this:

socket.on('connect', () => {
    socket
        .emit('sendAuthCredentials', { ... })
        .on('user joined', () => { ... })
        .on('user left', () => { ... })
})

But @EduardJS explains it very well:

What you need here is to make sure you attach the events only once, no matter how many re-connections you have

My solution was to take the listeners out of the connect callback, and only leave my auth check (which I do want to run on every connection attempt):

socket.on('connect', () => {
    socket.emit('sendAuthCredentials', { ... })
})

socket
    .on('user joined', () => { ... })
    .on('user left', () => { ... })

Any explanation to why this issue is marked closed?

I didn't close the issue, so I can't say.

That said, my issue was a problem with how I was attaching listeners, not so much a bug with socket.io

Hi @EduardJS - thank you for your explanation, it really helps understand what is happening. But I don't fully understand your fix. I posted a question on stackoverflow with the details of my code - https://stackoverflow.com/questions/44909405/socket-io-server-emits-multiple-times

would it be possible for you to take a look and tell me what I'm doing wrong? I don't fully follow where to implement this code:

for ( var event in this.events[ type ] )
    if ( !this.socket._callbacks[ '$' + event ] )
        this.socket.on( event, this.events[ type ][ event ] );

thank you!

best,
Mike

Was this page helpful?
0 / 5 - 0 ratings