Skip to content
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

client-side disconnect is not detected #635

Closed
domino14 opened this issue Nov 11, 2011 · 61 comments · Fixed by socketio/socket.io-client#394
Closed

client-side disconnect is not detected #635

domino14 opened this issue Nov 11, 2011 · 61 comments · Fixed by socketio/socket.io-client#394

Comments

@domino14
Copy link

var socketio = io.connect(socketServer, 
                {rememberTransport: false, 
                'reconnect': true,
                'reconnection delay': 500,
                'max reconnection attempts': 10,
                'secure': true});

socketio.on('disconnect', function() {
    alert('client socketio disconnect!')
});

The alert shows up if I take down the Node server, but not if I turn off my wireless, or close my laptop and re-open it later. The connection is lost though. Is there a better way to detect disconnect on the client side? This is with the WebSockets transport.

@ludovicbarreca
Copy link

Hello,

Did you find a solution to this ?

@drewww
Copy link

drewww commented Jan 28, 2012

I'm curious about this too. I'm having trouble getting disconnect events to fire reliably regardless of the situation, but this may be my own fault.

@fixe
Copy link

fixe commented Feb 12, 2012

+1

@domino14
Copy link
Author

I found a pseudo-solution where I do io.emit('ping') every 30 seconds or so on the front-end. If there has been a disconnect, this ends up triggering an automatic reconnect.

@normanwenk
Copy link

Here is my test, all on Mac using FF 10.0.2, Chrome 17.0.963.79 and Safari 5.1.2 (6534.52.7)
socket.io version = 0.8.7
node.js version = v0.6

The client app listens on all available io events.. connect, connecting, connect_failed, disconnect, reconnecting, reconnect and reconnect_failed and logs out to console

the situation.. i am connect on all browser via websockets

now i turn off wifi =>
FF: no event
Chrome: no event
Safari: event = disconnect

i send a ping from FF and Chrome to provoke a disconnect event =>
FF: no event
Chrome: no event

i turn on wifi again =>
FF: no event
Chrome: no event
Safari: event = reconnect

i send messages between the clients =>
all 3 browsers receive the messages, so the auto-reconnect seems to work, even though the events are not fired in ff and chrome

@KasperTidemann
Copy link

+1

1 similar comment
@chaobin
Copy link

chaobin commented Oct 31, 2012

+1

@tommykamkcm
Copy link

similar situation here. I've 2 device ipod touch (iOS 4.2.1) + galaxy note. galaxy note can always detect the disconnection of ipod touch while the ipod cannot. Seems safari block incoming data via websocket=[

@DarkXin
Copy link

DarkXin commented Jan 28, 2013

Still having this issue. I read some posts describing the same issue one year ago. I think i have to work around it myself? ...

@baloca
Copy link

baloca commented May 29, 2013

+1

2 similar comments
@bvallelunga
Copy link

+1

@callmephilip
Copy link

+1

@3rd-Eden
Copy link
Contributor

Just a small heads up, if you wrap socket.io with primus this issue would be resolved. It uses a combination of ping packets and online/offline events to determine these connections issues.

@pwhisenhunt
Copy link

I was able to fix this issue by adjusting the heartbeat timeout and heartbeat interval settings on the server, which I believe dictates the client side heartbeat. For example, if you'd like the client to trigger a disconnect after it does two heartbeats every 4 seconds and doesn't get a response then you would configure like the following.

io.set('heartbeat timeout', 10) io.set('heartbeat interval', 4)

@danpe
Copy link

danpe commented Apr 16, 2014

+1

@meepeek
Copy link

meepeek commented Apr 18, 2014

2 years and no solution at all ? Why Safari is the only browser that could detect the disconnect ? FF and Chrome do not follow the standards ??

@bvallelunga
Copy link

+1

@harpreetkhalsagtbit
Copy link

Thanks @pwhisenhunt

@dev0x10
Copy link

dev0x10 commented Jun 5, 2014

@pwhisenhunt but for some cases decreasing heartbeat causing another problem.
For example if the network is not stable, socket will disconnected too often because the heartbeat is too short.
I hope this issue will be fixed soon

@pwhisenhunt
Copy link

Yep, that's correct. Thanks for bringing that up! Sorry I must have forgotten that in my previous comment. I'm curious if this is fixed in 1.0?

Please pardon any misspellings, this message was sent from my iPhone.

On Jun 5, 2014, at 9:53 AM, dev0x10 notifications@github.com wrote:

@pwhisenhunt but for some cases decreasing heartbeat will causing another trouble.
For example if the network is not stable, socket will disconnected too often.
I hope this issue will be fixed soon


Reply to this email directly or view it on GitHub.

@AkashSaikia
Copy link

Any solution to "disconnect event not getting fired" yet? or am I missing something. As the last solution suggested by @pwhisenhunt is not so reliable.

mpaf pushed a commit to mpaf/pong-AI that referenced this issue Sep 10, 2014
@sthang
Copy link

sthang commented Jul 30, 2015

We are having this same issue on 1.3.6 version of socket.io. The node server in our case is not getting the disconnect event from client when wireless is shut off or laptop is closed.

@blented
Copy link

blented commented Aug 17, 2015

+1

@protozoo
Copy link

I am experiencing this same issue, using version 1.4.3. Why is the issue closed?
Thanks

@iamisti
Copy link

iamisti commented Apr 28, 2016

Please re-open this ticket, since it's not yet fixed!
I'was looking at the file: https://github.com/socketio/socket.io-client/blob/master/lib/manager.js to figure out if there is any option for that, and I found timeout which is 20 second by default.
But when I've tried to change it to 4 sec, it just didn't work at all.

@probil
Copy link

probil commented May 12, 2016

Have the same issue. Could be reproduced in chrome without actual internet disconnection. Just open Developer tools -> Network tab -> Choose offline from selectbox.

@aeolusheath
Copy link

any news that can work?

@darrachequesne
Copy link
Member

  • Did anyone try to debug with localStorage.debug='*'?
  • Does it happen only with websocket transport?
  • Which version of socket.io are you using?

@darrachequesne
Copy link
Member

darrachequesne commented Dec 13, 2016

I just tested with the chat example (socket.io 1.7.2 ; chrome ; linux):

image

Websocket gets established:
23:09:37.709 => ping
23:09:37.934 => pong (server response)
23:10:02.938 => ping
23:10:03.169 => pong
I switch off the WIFI
23:10:28.171 => ping
wait for 60s => timeout => disconnect gets fired

25s being the default value for pingInterval, 60s for pingTimeout (ref)

Can anyone confirm/infirm that behaviour?

Also, if the server gets killed, I think that the disconnect event would be fired immediately since the underlying TCP connection is closed.

@creole
Copy link

creole commented Jan 5, 2017

I can confirm this behavior: disconnect gets fired on both server and client if a network cable is unplugged. However, there is also the case where the client gets disconnected from the server without any events being fired. The below screenshots are from a client that is no longer emitting to the server. No disconnect events have been fired (either on the client or on the server). Note that the client still seems to be receiving pongs from the server:

socketio

socketio2

socketio3

@darrachequesne
Copy link
Member

there is also the case where the client gets disconnected from the server without any events being fired

Hmm, I don't understand, how do you know the client gets disconnected then?

@creole
Copy link

creole commented Jan 6, 2017

Yeah, "disconnected" is probably not the right wording. The issue is that the client stops emitting to the server, although it is still receiving pongs from it. In the last screenshot I posted, socket.emit should have been called in between the ping pong events, but somehow it hasn't.

@darrachequesne
Copy link
Member

So, if I understand correctly, the socket is still emitting pings/getting pongs, but socket.emit() gets discarded?

Can you reproduce easily? Is it linked to a given browser?

Ref: https://github.com/socketio/socket.io-client/blob/1.7.2/lib/socket.js#L155

  if (this.connected) {
    this.packet(packet);
  } else {
    this.sendBuffer.push(packet);
  }

But the only way the connected flag is set to false is here:

Socket.prototype.onclose = function (reason) {
  debug('close (%s)', reason);
  this.connected = false;
  this.disconnected = true;
  delete this.id;
  this.emit('disconnect', reason);
};

So it shouldn't be discarded here, since you didn't get the disconnect event. Else, if we look in engine.io-client:

Socket.prototype.sendPacket = function (type, data, options, fn) {
  //...
  if ('closing' === this.readyState || 'closed' === this.readyState) {
    return;
  }

The readyState flag is updated here.

@creole
Copy link

creole commented Jan 6, 2017

So, if I understand correctly, the socket is still emitting pings/getting pongs, but socket.emit() gets discarded?

Yes, that's it. Will try to find a way to reproduce.

@creole
Copy link

creole commented Jan 7, 2017

@darrachequesne Turns out my own code was blocking calls to socket.emit. Apologies for having wasted your time. My issue was not the same as the issue of this thread, and certainly not an issue with socket.io.

@darrachequesne
Copy link
Member

darrachequesne commented Jan 8, 2017

@creole great, thanks!

To all others who +1'ed, has my comment #635 (comment) fixed (or at least explained) your issue?

In any case, maybe a smaller default value for pingTimeout would help? Currently in the worst case one must wait 85s (25000 (pingInterval) + 60000 (pingTimeout)) before getting a disconnect event. How about a pingTimeout of 5s by default (which is what @mbf5923 suggested, btw)?

@llaakso
Copy link

llaakso commented Jan 11, 2017

Changing default setting so much can lead to unexpected behavior in some implementations, but I agree dropping pingTimeout to around 30s would be more purposeful.

@jamilservicos
Copy link

@grobjin9
Copy link

Experiencing this problem as well.. Changing ping interval does not seem reliable enough in production

@grobjin9
Copy link

grobjin9 commented Mar 9, 2017

As long as the bug will not be resolved shortly and a final purpose of what we need is to indicate if user has left, we can extend our socket object by using middleware. Basically, we need to extend socket object with a user and a room the user is currently in and after user got disconnected we can use that properly as we need. Full code is available at: https://github.com/abitlog/retube/blob/master/server/utils/socket.js

  io.use(checkAuth);

  io.on('connection', function (socket) {
    socket.on('join chatroom', function (data) {
      const { id: room } = data;

      socket.join(room);

      io.to(room).emit('join chatroom', {
        user: socket.user,
        counter: socket.adapter.rooms[room].length
      });

      socket.currentChatroomId = room; // extend an object after user joins a room
    });

    socket.on('leave chatroom', function (data) { // this event will not be fired as long as client-side disconnect does not work
      const { id: room } = data;

      io.to(room).emit('leave chatroom', {
        user: socket.user,
        counter: socket.adapter.rooms[room] ? socket.adapter.rooms[room].length - 1 : null
      });

      socket.leave(room);
    });

    socket.on('disconnect', function () {
      const { currentChatroomId } = socket;

      io.to(currentChatroomId).emit('leave chatroom', { // we use currentChatroomId from our socket object to indicate the room user has left
        user: socket.user,
        counter: socket.adapter.rooms[currentChatroomId] ? socket.adapter.rooms[currentChatroomId].length  : null
      });

    });
  });

  function checkAuth(socket, next) {
    if (!socket.request.session.passport) {
      next(new AuthError(404));
      return;
    }

    socket.user = socket.request.session.passport.user;

    next();
  }

@darrachequesne
Copy link
Member

@abitlog I may be missing something here, but your use case is not related to the current issue, right?

Please take a look at the disconnecting event.

@KamWis
Copy link

KamWis commented Mar 17, 2017

@darrachequesne I investigated the issue and it seems all events are working fine. It's just in Chrome for mac (didn't notice this in windows version) taking long time (approx 1 min) to trigger disconnect. I tried of course timeout and connect_error as attempt to suplement disconnect as a sibling event but no luck there.

@darrachequesne
Copy link
Member

@KamWis which value are you using for pingTimeout/pingInterval?

@brenc
Copy link

brenc commented Apr 5, 2017

I just went through all of my connection settings again and I must have had a typo somewhere. When I set pingTimeout and pingInterval on the server, the client appears to respect that even in Chrome. If anyone else is having problems and wants to test this, it helps to set localStorage.debug = 'engine.io-client:socket' in your browser. This will make ping/pong messages show in the console.

@darrachequesne
Copy link
Member

I guess the issue can be closed now?

@brenc
Copy link

brenc commented Apr 6, 2017

Yep, I believe so. Looks like everything is working as expected.

@Royalone94
Copy link

I can detect disconnect event but it took time at least 8-10 seconds.
would you tell me why it does happen?

@darrachequesne
Copy link
Member

@Royalone-mobile please update the pingInterval / pingTimeout values.

@liujiusheng
Copy link

I have solved this problem.
it may be a bug of chrome. it‘s still online when we set the network to "offline" mode(谷歌浏览器把网络模式设置为offline的时候websocket好像同样可以通信,网络并没有真正断掉,可以换用两个设备用物理上的断网方式你们自己验证一下是不是这个原因).
the right way is use socket.on('disconnect',function(){}).
but pingInterval default value is 25000,pingTimeout default value is 60000.it's too long.
so we need to set pingInterval / pingTimeout to a small value.
(其实disconnect事件是可以监听到用户掉线的,只是谷歌浏览器的使用不当埋了第一个坑,然后这个自动掉线检测时间比较长又埋了第二个坑,只需要把pingInterval设置短一点就可以很快检测到用户掉线了)

@developerKumar
Copy link

Hi guys,

Any luck with this? I am also facing the same issue.

@irvanherz
Copy link

Got it working smoothly on local server. Socket io fire disconnect event immediately each client disconnected. But dunno why it didn't same on real server

@pankajgupta1
Copy link

on mobile device working fine, but facing same problem on desktop/laptop.

sunrise30 added a commit to sunrise30/socket.io-client that referenced this issue Jan 8, 2022
darrachequesne pushed a commit that referenced this issue Jul 4, 2024
Should call callback on open
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.