I am trying to get a handle on the various connection/disconnection events and how to use these to make sure that my application will always terminate gracefully.
I understand that socket.io will automatically attempt to reconnect a specified number of times. It is my understanding that as the connection goes down and subsequently reconnects there will be a disconnection event fired server side. I do not care about the connection temporarily going down so long as it comes back up at some point.
However if there is a more permanent disconnect, I do care about this and would need to update data such as connected users. I understand that on the client side you can get a reconnect_failed error object but I do not believe you can listen for this on the server. Is there any way to get notification on the server side that the connection is down and reconnection has failed? If so how does socket.io implement this?
I could issue a timeout upon a disconnection event server side that removes users if there is no reconnection. I could also have the server ping all connected clients at certain intervals. Are these kinds of solutions the only way to completely deal with all kinds of possible disconnections?
Related
How does the server know when the client suddenly dies/disconnects due to network/power failure in SocketIO. Since the client wont have any chance to emit a disconnect event to the server... is there any way to solve this issue?
Socket.io has an internal keep alive mechanism. If a client disconnects abruptly, the server doesn't know about it immediately. Instead, when the next keep alive mechanism event will fire and no response will arrive within the time limit, the server will fire disconnect event for that client. The time it takes for the server to detect a client disconnected is affected from the keep alive polling intervals and the timeout limit.
You can change those values using 'pingInterval' and 'pingTimeout', which will change the way engine.io is configured.
I am making a game where a node server speaks to javascript clients using socket.io. Players can connect and disconnect from the game and the server keeps track of who is connected. However, I have found that on many occasions when i close the server, close all open client tabs, then restart a new node server, the number of clients connected seems incorrect.
For example, I will connect with just one client but the node debugger shows that the server is keeping track of three sockets.
This is a problem because often these orphaned clients will receive messages from the server or timeout, and this messes up the game logic on the server (it was not expecting this many players etc.)
I think the reason this is happening is:
1. Clients in socket.io automatically attempt a reconnect periodically when they are disconnected
2. When closing a tab the sockets associated with that page are not being "flushed" or cleared for some reason.
3. When the server is closed and then started up again, these unflushed clients think "oh, the server is back up, i will try and reconnect"
How can I tell the difference between sockets that have had their tabs closed/were associated with the old server, and new clients attempting to connect to the newly restarted server? Or is there a way for me to ensure the clients get "flushed" when either the server is closed or a tab?
Without any code, I am really only guessing here.
http://socket.io/docs/#sending-and-receiving-events
Above, you will find code and I will copy it. Basically, you need to listen to the 'disconnect' event on the socket and remove your reference of the client from whatever array you are using to keep track of your clients.
socket.on('disconnect', function () {
// remove from list here
});
Connections from the browser will die on tab close and this event will be called when this happens. Yes, if you reopen the page, they will reconnect.
You should create some sort of "handshake" that actually adds a client to your list of game clients. Anyone can technically connect to a websocket. It can be as simple as emitting an "init" message that is empty but at least have something there.
In my ASP.NET MVC app, the user clicks a button on the UI to make a phone call. An ajax request goes to the MVC app, which calls a phone dialer -- a method in library that calls an external component to make a call.
If a dialed call is terminated by the recipient of the call, the phone dialer component raises an event by calling an event handler in its own class.
I want to propagate that event to the client side so that it may update its UI.
An Option I Can't Use
I've looked at JavaScript Server-sent events. However, they are different from my situation in the way that in a JavaScript Server-sent event, here's what happens:
1) The client initiates a connection on a new socket to the server. The key difference being, the client initiates the connection.
2) The connection is held live and active until the server or the client want to terminate it.
3) The server has to be alive all throughout the time from the time the connection is made until the client or the server want to terminate the connection and no longer exchange notifications. This means that a new socket connection and consequently a new worker thread to service the notification exchange is used per client.
If I use server-sent events, I will have to make a server that stays alive. That means I will have to have a new action on a controller and a corresponding view that gets called at the very beginning and stays alive until the notification about the call hang-up is received.
This can not only be expensive, it is also counter-intuitive to my design as I do not want to be redirected to a new View just to listen to events.
Anyone have any other alternative?
You have to either use a WebSocket or Long polling. These both require you to set up a connection from the client to the server, additional to the normal HTTP cycle. And what else would you expect? When the page is sent, the communication between client and server is done. The HTTP cycle is over, no more data can float through. The new connection needs to originate from the client because the client does not allow arbitrary incoming connections.
I do not think there are other alternatives in normal case.
SignalR, etc, all require connection to be alive or periodically restarted by client. I am not aware of anything that allows server to initiate connection with a browser (it does not even seem technically possible due to proxies/firewalls etc).
So basically, if I have say a chat application using websockets, I want to be able to send the server a message saying I'm disconnecting. I've tried binding to onbeforeunload, but that seems to only be able to display a message.
Is there a better strategy to this? If not, it seems like I'd have to do some sort of ping/timeout strategy from the server side.
Thanks.
WebSockets are implemented on top of TCP, and in TCP world different connection drops - is expected scenario.
In terms of network security - your server side should never rely on "kindness" of clients, and should always be independent and expect any and more scenario of disconnects.
Taking this in account, you have to expect unexpectedly dropped connections (GPRS/EDGE/3G/4G poor connection or going under bridge/ground, wifi drops, ethernet unplug, ISP issues, server network problems, and many more). Dropped connections without "bye" in fact is most common disconnects you will get, so have to implement server side logic taking this in account.
Here's the scenario, I have a client side application, served by PHP on a different server to the node.js + socket.io application. It can connect and receive broadcasts sent from the server. If the connection drops, the application falls back to polling a database (using setInterval()). It attempts to reconnect every 5 polls, and it can successfully reconnect and continue to receive messages.
My problem occurs when the user loads the page and the node server cannot be reached (I turned it off for testing), I then turn on the server and on the 5th poll, it successfully connects to the server, using socket.socket.reconnect();. However, whenever the server broadcasts messages, it doesn't fire the event. Note that this doesn't happen when testing on a phone (which falls back to a different socket method)
I have already seen the question found here Reconnection in socket.io problem in `socket.on('message',function(){})`, however, the socket has not previously been connected so I don't think it could be the session?
EDIT: I changed the socket.socket.reconnect() to socket.socket.connect() and it fixed the problem. If someone could explain the reasons of why this works I'd like to know. I know its because the server isn't actually reconnecting, but would like more info.
Thanks.
well you possibly know the reason for this. server is not reconnecting. it is actually connecting. when you tell socket.io to reconnect it searches for the previous connection handle and thats where the problem arises.