New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Node.js socket.io Page refresh Multiple Connections opens #2844

Closed
mcbookwood opened this Issue Jan 30, 2017 · 6 comments

Comments

Projects
None yet
5 participants
@mcbookwood

mcbookwood commented Jan 30, 2017

Note: for support questions, please use one of these channels: stackoverflow or slack

You want to:

  • report a bug
  • request a feature

Current behaviour

If i run this code und press F5 several times, in some cases new connection is created, before the old one is disconnected. After some time, i think its the Heartbeat Timout, all the connections will be closed. See the result:

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

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

    console.log(' %s sockets connected', io.engine.clientsCount);

    socket.on('disconnect', function() {
        console.log("disconnect: ", socket.id);
    });
});
2 sockets connected
 3 sockets connected
 4 sockets connected
 5 sockets connected
 6 sockets connected
 7 sockets connected
 8 sockets connected
 9 sockets connected
 10 sockets connected
 11 sockets connected
disconnect:  0h_9pkbAaE3ftKT9AAAL
 11 sockets connected
 12 sockets connected
 13 sockets connected
 14 sockets connected
disconnect:  oB4HQRCOY1UIvvZkAAAP
 14 sockets connected
 15 sockets connected
disconnect:  LiIN0oDVoqbePgxFAAAR
 15 sockets connected
 16 sockets connected
 17 sockets connected
 18 sockets connected
disconnect:  zxvk-uhWABHzmu1uAAAV
 18 sockets connected
 19 sockets connected
 20 sockets connected
disconnect:  FlboxgTzcjf6ScffAAAY
 20 sockets connected
 21 sockets connected
disconnect:  9UGXbnzukfGX_UtWAAAa
 21 sockets connected
disconnect:  pAfXOEz6RocKZdoZAAAb
 21 sockets connected
disconnect:  DIhTyVgG2LYBawaiAAAc
 21 sockets connected
disconnect:  W4XOc1iRymfTE2U0AAAd
 21 sockets connected
disconnect:  WZzegGPcoGDNLRTGAAAe
 21 sockets connected
 22 sockets connected
disconnect:  KVR3-fYH0cz77BmgAAAC
disconnect:  ANQknhnxr4l-OAuIAAAD
disconnect:  KZE5orNx6u9MbOArAAAE
disconnect:  TS6LL3asXrcznfcPAAAF
disconnect:  SVNxS3I7KqecdqKhAAAG
disconnect:  IE2WE5Y0PJzvxgBfAAAH
disconnect:  v69bdJav9PjpThBGAAAI
disconnect:  mJKT1ggfOOTshZKgAAAJ
disconnect:  YlycVjdcWe0emCAcAAAK
disconnect:  MoIDJSzP_L-1RUwuAAAM
disconnect:  wAl0x5qwCkrnDDYQAAAN
disconnect:  eiTlPEk2Hx_X-L-fAAAO
disconnect:  KgkrXxzG_EpXOsPTAAAQ
disconnect:  Lvf3kK-6XXEbu3NWAAAS
disconnect:  -hOoGdYOIvVK04K_AAAT
disconnect:  3EUmaAYpK-U3Ss9tAAAU
disconnect:  HQ6M98FebtKlU3OfAAAW
disconnect:  OwgrbRBYbS4j84nmAAAX
disconnect:  yN8FZAP4RjUNl2MeAAAZ
disconnect:  K9IFTjlgAWzdNfpUAAAf

Steps to reproduce (if the current behaviour is a bug)

Note: the best way to get a quick answer is to provide a failing test case, by forking the following fiddle for example.

Expected behaviour

The expected bahaviour is, that each connection is disconnected, before a new one is opened.

Setup

  • OS: Windows
  • browser: Firefox, Chrome, IE
  • socket.io version: 1.5

Other information (e.g. stacktraces, related issues, suggestions how to fix)

@darrachequesne

This comment has been minimized.

Show comment
Hide comment
@darrachequesne

darrachequesne Feb 1, 2017

Contributor

I guess that's because the underlying TCP connection is not properly closed when the page is refreshed, so the disconnect event is triggered by the ping timeout, as you said.

So I'm not sure we can do much about that. (you can decrease the pingTimeout and pingInterval values, to control the heartbeat behaviour)

Contributor

darrachequesne commented Feb 1, 2017

I guess that's because the underlying TCP connection is not properly closed when the page is refreshed, so the disconnect event is triggered by the ping timeout, as you said.

So I'm not sure we can do much about that. (you can decrease the pingTimeout and pingInterval values, to control the heartbeat behaviour)

@mcbookwood

This comment has been minimized.

Show comment
Hide comment
@mcbookwood

mcbookwood Feb 1, 2017

I got an explanation and a workaround here:
http://stackoverflow.com/questions/41924713/node-js-socket-io-page-refresh-multiple-connections

If you force socket.io to use only websockets and not to start with http polling, this issue doesn't occure.

mcbookwood commented Feb 1, 2017

I got an explanation and a workaround here:
http://stackoverflow.com/questions/41924713/node-js-socket-io-page-refresh-multiple-connections

If you force socket.io to use only websockets and not to start with http polling, this issue doesn't occure.

@darrachequesne

This comment has been minimized.

Show comment
Hide comment
@darrachequesne

darrachequesne Feb 16, 2017

Contributor

Please be aware that if you only use websocket, you loose the fallback to long-polling in case there is for example a proxy / a firewall not allowing websocket connections.

You can also play with pingTimeout and pingInterval options, to somewhat mitigate that behaviour.

Contributor

darrachequesne commented Feb 16, 2017

Please be aware that if you only use websocket, you loose the fallback to long-polling in case there is for example a proxy / a firewall not allowing websocket connections.

You can also play with pingTimeout and pingInterval options, to somewhat mitigate that behaviour.

@jamilservicos

This comment has been minimized.

Show comment
Hide comment
@jamilservicos

jamilservicos commented Feb 24, 2017

@aktiwers

This comment has been minimized.

Show comment
Hide comment
@aktiwers

aktiwers Jan 6, 2018

I'm still having this issue.

aktiwers commented Jan 6, 2018

I'm still having this issue.

@ayotycoon

This comment has been minimized.

Show comment
Hide comment
@ayotycoon

ayotycoon Aug 9, 2018

For anyone still having this issue. here is how i fixed it.
let me explain.
once the page refreshes or a new tab is opened, socket dosen't really care so it opens a new connection every time . this is more of a advantage than disadvantage. the best way to tackle the issue is on the server side, once a user logs in with his or her user name , you can send that name along with the query options on the client so it can be used as a unique identifier. in my case i used a token

this.socket = io.connect(`${environment.domain}` , {
      query: {token: this.authservice.authToken}
    });

then on the server side you can create an empty array to a key and an array of values. the username of the user will be used as a key and the corresponding array of socket as the value. in my own case like i said i used a token

const users = [ ]
socket.nickname = (decoded token username);
users[socket.nickname] = [socket];

then you can perform a simple logic to check if a user already exists in an array, if it does, push the new socket to the array of the user

if ( user.username in users) {
                    console.log('already exists')
                    users[user.username].push(socket);
                } 

if it dosent, just create a new key and add the socket as the key.(make sure its an array because a user can always refresh or open a new tab with the same account and you dont want the chat message to deliver in one tab and not deliver in another)

else {
                    socket.nickname = username;
                    users[socket.nickname] = [socket];
                    
                }

then to emit a message you simply loop through the array and emit the message accordingly. this way each tab gets the message

socket.on('chat', (data) => {

            if (data.to in users) { 

                for(let i = 0; i < users[data.to].length; i++) {
                    users[data.to][i].emit('chat', data)
                }
                for(let i = 0; i < users[data.user].length; i++) {
                    users[data.user][i].emit('chat', data)
                }


            }
        })

you can add a disconnect logic to remove the socket from the users array too to save memory, so only currently open tabs acre active and closed tabs are removed. i hope it solved your problem

ayotycoon commented Aug 9, 2018

For anyone still having this issue. here is how i fixed it.
let me explain.
once the page refreshes or a new tab is opened, socket dosen't really care so it opens a new connection every time . this is more of a advantage than disadvantage. the best way to tackle the issue is on the server side, once a user logs in with his or her user name , you can send that name along with the query options on the client so it can be used as a unique identifier. in my case i used a token

this.socket = io.connect(`${environment.domain}` , {
      query: {token: this.authservice.authToken}
    });

then on the server side you can create an empty array to a key and an array of values. the username of the user will be used as a key and the corresponding array of socket as the value. in my own case like i said i used a token

const users = [ ]
socket.nickname = (decoded token username);
users[socket.nickname] = [socket];

then you can perform a simple logic to check if a user already exists in an array, if it does, push the new socket to the array of the user

if ( user.username in users) {
                    console.log('already exists')
                    users[user.username].push(socket);
                } 

if it dosent, just create a new key and add the socket as the key.(make sure its an array because a user can always refresh or open a new tab with the same account and you dont want the chat message to deliver in one tab and not deliver in another)

else {
                    socket.nickname = username;
                    users[socket.nickname] = [socket];
                    
                }

then to emit a message you simply loop through the array and emit the message accordingly. this way each tab gets the message

socket.on('chat', (data) => {

            if (data.to in users) { 

                for(let i = 0; i < users[data.to].length; i++) {
                    users[data.to][i].emit('chat', data)
                }
                for(let i = 0; i < users[data.user].length; i++) {
                    users[data.user][i].emit('chat', data)
                }


            }
        })

you can add a disconnect logic to remove the socket from the users array too to save memory, so only currently open tabs acre active and closed tabs are removed. i hope it solved your problem

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment