Handling reconnections in the socket.io server? - node.js

When the socket.io client performs an (automatic) reconnection - as might happen if a mobile client went to sleep then woke up again - does the server get a reconnect event? Or does it just see a disconnection and fresh connection?
In either case is there a way to
identify that it's the same client e.g. by a unique client id that persists across connections
have the client automatically re-join any rooms it was in before
Or do I need to code that functionality manually e.g. by having the client supply the id or rooms itself on reconnection?
I had a read of the socket.io docs and can't see any list of events that the server might receive.

Related

What is the better strategy for notifying the client that a webhook has been received by the server?

There are two methods I am considering. One is to set up a subscriber function with the socket ID that is fired once the webhook is received. The other is to poll the server from the client to check if the DB has been updated.
I don't like the idea of polling the server because it is making unnecessary network calls. However, the problem I see with the subscription method is that if the socket connection disappears for whatever reason, the client will never be notified.
I am using Sails.js and Mongoose

Tell server that user is no more on internet

I am new to node.js and trying to develop group chat using node.js and socket.io. I am able to do group chat also able to manage data in the system.
Now, the problem with me is with offline users i.e not connected to internet.
I am having connection stream of this user and as if I do receiverUserSocket.emit("sendMsg",data) there is no way to verify if this user received message or not.
Yes, there is an event .on("disconnect") but I am getting delay of approx 30 - 40 seconds.
Is there any way we can identify that the user to whom we want to send message is online or offline.
The best way is to use socket.io heartbeats - assuming you're using socket.io.
Heartbeats and the problem with detecting a terminated connection are well explained here:
Advantage/disadvantage of using socketio heartbeats
Keep in mind that you can control heartbeat timeout values (thus forcing the disconnect event to appear much faster), as explained here:
Controlling the heartbeat timeout from the client in socket.io
But that might put much more strain on your server.

how to send a message to individual clients with socket.io with multiple server processes?

I'm about to begin with socket.io and this is more of a theoretical question,
let's say that I want to send a message to a specific user with socket.io,
normally I would have to store the socketid with the relevant userid and when sending, get the socketid and send to.
but what if I have mutliple server processes running ? I'll have to make sure the correct server that the client is actually connected to does the sending. is it possible ?
For multiple server instances, you need to have a caching service (memcache, redis) for authentication and a central message queue service (stormMQ, rabbitMQ, AQ, java-based mq) where all your node instances bind to. Thus, a Node instance binds to the message queue for each client / channel / whatever, and all the other bound Node instances receive the messages and forward them to the client.
The problem is typically about how to play with a WebSocket cluster:
Several front-end servers which will be in charge of handling bidirectional connections with each client. They form the WebSocket cluster.
Several back-end servers which will be in charge of handling the business logic of your application.
Each time the back-end wants to inform the client, it will send a request to the WebSocket cluster which has the responsibility to communicate with the client.
A possible scenario:
Identify each WebSocket cluster's server with a unique id.
Identify each client with a unique id.
Each time a client will connect one of your WebSocket cluster's server, store its unique id along with the server's unique id in a a distributed key/value like database.
Thus you know which client is connected with which server.
The next time your back-end application wants to notify a client there are two possibilities:
The pair (clientId, serverId) is not present in the database and you cannot inform the client.
The pair (clientId, serverId) is present in the database, then you have to ask to the server identified by serverId to notify the client identified by clientId.
Notes:
Each WebSocket cluster's server can run a node.js instance supercharged with socket.io. It has to provide a route which will take the clientId as a parameter and will use socket.io to notify this client. Indeed, socket.io is aware of whcih client is using which socket on this server.
Every time your server will crash, you have to clean your database and remove all pairs which contain the server id.
Deploying a WebSocket cluster can be tedious, so you have commercial offers like Kaazing.
A good distributed key/value like database is Riak. It is better than Redis or Memcached for the above purpose because it can be easily distributed in a data-center and over several data-centers.

Scaling NodeJS chat room - store connection status in Redis

The chat room app are running on multiple servers and consists two services:
1. connection manager
Before joining the chat room, client ask for a chat service url from connection manager first
2. chat service
A typical socket.io based chat implementation.
I need to store each client's connection status in Redis, such as user connect to which room, how many users are in one room etc. So the connection manager can use the data to do load balancing.
I can use socket connection/disconnect event to maintain the current connection status in Redis, but in case of NodeJS server failure, how to make sure Node and Redis data are synchronized? What's the best way to do this?
I can use socket connection/disconnect event to maintain the current
connection status in Redis, but in case of NodeJS server failure, how
to make sure Node and Redis data are synchronized?
For example you can create a set in redis which would contain reference to keys that are managed by specific server node. If a node goes down or is restarted you can invalidate these keys.

Weird Socket.IO behavior: events "on connection" and "on disconnect" happen almost at the same type

On the socket io server I have something like:
io.sockets.on('connection',function(client) {
console.log(client.id + ' connected at '+(new Date()).getTime());
client.on('disconnect',function() {
console.log(client.id + ' DISCONNECTED at '+(new Date()).getTime());
});
});
And my problem is that this happens:
debug - client authorized
info - handshake authorized 15229479751557595508
debug - setting request GET /socket.io/1/websocket/15229479751557595508
debug - set heartbeat interval for client 15229479751557595508
debug - client authorized for
debug - websocket writing 1::
15229479751557595508 connected at 1313769716321
debug - websocket received data packet 5:::{"name":"estimatepp","args":[9]}
debug - websocket received data packet 5:::{"name":"ready","args":[null]}
info - transport end
debug - set close timeout for client 15229479751557595508
debug - cleared close timeout for client 15229479751557595508
debug - cleared heartbeat interval for client 15229479751557595508
15229479751557595508 DISCONNECTED at 1313769716454
debug - discarding transport
I don't know if this is normal but as you can see, the client 15229479751557595508 connects at 1313769716321 and disconnects at 1313769716454, just 133 mili-seconds later (this number is always either 132 or 133). I'm not ordering the client to disconnect after something.
Any ideas on why does this happen ?
Also I have another doubt. If I listen for connection events on io.sockets.on, shouldn't I be listening for disconnect events also there ? Except there's no client there...
What is the correct way to listen for disconnections ?
Thanks for any help.
EDIT: You can ignore the lines
debug - websocket received data packet 5:::{"name":"estimatepp","args":[9]}
debug - websocket received data packet 5:::{"name":"ready","args":[null]}
It's part of the project I'm working on. Maybe the thing is that it just receives those events and after that because there's no activity for a while it closes the connection ? But this is not wanted behavior is it ?
The server-side code that you have posted is fine and should work as expected. Check for bugs in your client-side code (or post your client-side code here). If nothing there, try a different browser.
Regarding your disconnect event.
You have an io.sockets.on("connection", function (client) { ... }) event handler where when a new connection is made, a session is created for the connection and is stored in the client variable.
You then attach event handlers (like the disconnect one) to this client object.
Now when that client disconnects, the disconnect event handler attached to that particular client object is invoked.
Moreover, as you can see in Exposed Events — Socket.io, io.sockets.on only exposes the connection event.
I have similar thoughts as the creator of the question.
The time in ms is probably your roundtrip time to the server or the time it takes to manage connects with the client etc etc. So I wouldnt bother so much with the time factor.
I get same result when I refresh the client manually and repeatedly. between say half and one second intervals. This seems to create a scenario which otherwise only happen with poor network quality.
I can see in the logs that I get a connection, before a disconnection with the same socket.id.
client connected: qEcxQQCivSyKJVbF85dc
client disconnected: qEcxQQCivSyKJVbF85dc
However my on.disconnect event does in this scenario NOT fire.
On disconnects I clean up my local object of connected clients and I can see that I a client left in there and when I analyze the socket.connected status it is disconnected.
So under certain circumstances the above scenario causes a disconnect event to not fire.
Probably due to timings, asynch, network quality etc.
Two ways to go.
Build the application according to those constraints or
find someone who can come up with a more solid method for listening to on.disconnect, which, as the original question eluded, does not involve being attached to a specific socket client.
It is like the event listener is overwritten when the client connects again with the same id. A more general disconnect event listener would disregard that but potentially cause other issues instead.
I am personally going with option 1. and instead creating a garbage collector of sorts that clean up my local array of clients if they are disconnected.

Resources