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.
Hello,
Did you find a solution to this ?
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.
+1
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.
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
+1
+1
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=[
Still having this issue. I read some posts describing the same issue one year ago. I think i have to work around it myself? ...
+1
+1
+1
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.
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)
+1
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 ??
+1
Thanks @pwhisenhunt
@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
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 [email protected] 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.
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.
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.
+1
I am experiencing this same issue, using version 1.4.3. Why is the issue closed?
Thanks
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.
Have the same issue. Could be reproduced in chrome without actual internet disconnection. Just open Developer tools
-> Network tab
-> Choose offline
from selectbox.
any news that can work?
Saaaame issue!
Please reopen this, It's not fixed!
Agreed - this is still a problem for me also
hi
i use this solution and fine for me
var io = require('socket.io')(http, {'pingInterval': 2000, 'pingTimeout': 5000});
http://stackoverflow.com/a/31787022/2818627
Hi,
Still not found a good solution for this issue. I turned off my wifi connection set browser mode to offline still disconnect event of socket.io was not raised. was it due to local connection?
Regards,
Suhas
+1
Same issue. This issue needs to be fixed. I have this with Chrome 54.
+1
I have the same issue, event disconnect client-side not detected
localStorage.debug='*'
?I just tested with the chat example (socket.io 1.7.2
; chrome ; linux):
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.
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:
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?
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.
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.
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.
@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.
@creole great, thanks!
To all others who +1'ed, has my comment https://github.com/socketio/socket.io/issues/635#issuecomment-266880918 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)?
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.
It might be useful
https://gist.github.com/jamilservicos/e7c09e3701a7ba5ff817096ef8426d94
Experiencing this problem as well.. Changing ping interval does not seem reliable enough in production
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();
}
@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.
@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.
@KamWis which value are you using for pingTimeout/pingInterval
?
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.
I guess the issue can be closed now?
Yep, I believe so. Looks like everything is working as expected.
I can detect disconnect event but it took time at least 8-10 seconds.
would you tell me why it does happen?
@Royalone-mobile please update the pingInterval / pingTimeout
values.
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 usesocket.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设置短一点就可以很快检测到用户掉线了)
Most helpful comment
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.