How to change status of perticular user when socket is disconnect? - node.js

II am here to resolve my problem in socket connection and disconnection. I want something like this
1. connection done. (ok) // working
2. on perticular event I am doing to update location of user in database { Here user is online }.
3. But somehow network disconnection the socket will be disconnect and user must be offline. this can be using disconnect event. but I am not aware how to recognise that perticular user has to be updated offline because I don't have user_id in `socket.on('disconnect')` event. please help me out. I googled it everywhere but not helped me out.
sorry for wanting logic but it is really needed to me.
Thanks in advance. :)

On disconnect, like you mentioned, you can track the id based on this.id or socket.id.
socket.on('disconnect', function() {
console.log(this.id);
console.log(socket.id);
});
Alternatively, you can handle sockets by using a global array, as suggested in this answer.
If netiher of those are suitable, you can do some dependency injection on the socket object
io.on('connection', function(socket) {
//Obtain the user_id somehow and add it into the socket object
socket.user_id = "hello_world";
socket.on('disconnect', function() {
console.log(socket.user_id);
});
});

Related

Socket.io 'disconnect event' firing too late after reconnect

I've a simple code which set offline for the user in my sql database.
Server
io.on('connection', function (socket) {
ApiHelper.setUserOnline(socket.token);
socket.on('disconnect', function () {
ApiHelper.setUserOffline(socket.token);
});
}
So lets say,
An user connect to socket than he lost the network connection then reconnect.
I get this logs.
User connected (he is online)
Network losted.
Network losted but disconnect event has not received by server yet, so user is still online
User reconnect to network and then socket. User is still online.
Previous disconnect event recevied by server and user is set offline in database. But wait user has just reconnect so actually user must be online.
Because of disconnect event fired late we saw the user is offline in database.
How can I achieve this problem?
I think the best way is to store the socket.id in the sql database, so when a user login / connects you first check if that user.account is already online or not.
If it is online, then use the old socket.id to notify that the account has been opened from another window/device/whatever and replace it in the db for the new socket.id
and by replacing the old socket.id for the new one in the db, when a disconnect occurs you will really know if it was the currently active client (socket.id) using that account or not.
So at the disconnection : check if the disconnecting socket.id is in the database or not
(in other words : currently connected or not)
io.on('connection', function (socket) {
/* check if the account associated to this socket was
previously associated to another socket.id ...
(that might be currently connected or about to disconnect (lost connection)
*/
if(thisAccountWasOnlineBefore){
socket.to(old.socket.id).emit('exit', 'account opened from another session');
}
//pass also the socket.id so you can store it in the db
ApiHelper.setUserOnline(socket.id, socket.token);
socket.on('disconnect', function () {
//check if socket.id is associated to any account in the db
// if true : remove the socket.id and set as account status : offline
});
}

Socket.IO: connection to a non-existing namespace

First post, i'll try to be as clear as possible :)
I'm trying to create on Demand namespaces on my SocketIO/NodeJS App.
Basically, the server create a specific namespace for each client.
I need to handle, server side, the case where the client try accessing a non-existing namespace.
The idea is to avoid any unwanted connection server-side, or at least, handle it to force the disconnection.
But while testing, it seems that when i try this, on client Side :
var socket = io("thisNameSpaceDontExist");
socket.on('connect', function(){
window.console.log('connected to server');
})
The 'connect' event won't trigger, which seems perfect !
Doing a console.log on socket, it displays this:
connected: false
disconnected: true
But the main problem, is that, Server Side, it's different, there is an active connection...
While doing some research, i found this issue https://github.com/Automattic/socket.io/issues/1867, still, i'm on the last version at this time: 1.3.5
for information, the socketIOHandler code i'm using:
io.on('connection', function (socket) {
console.log("[SocketIOHandler::Connection] +1");
socket.on('disconnect', function () {
console.log("[SocketIOHandler::Disconnection] -1");
});
});
PS:
Also find some issues and MR claiming the support of dynamic namespaces: https://github.com/Automattic/socket.io/issues/1854, but these are not merged, so i don't really understand the behavior on my code...
Thank you!

Socket.io : what happen to the client(socket) after a user is disconnected? Can I/Should I remove it?

I am using socket.io, and I want to know how can I remove the client(socket) after a connection is closed. (In fact, I don't know what is going on after a connection is close, will that socket remained there? Should I remove it? Will it take up memory?)
My code:
socket.No = socketNo++;
io.sockets.on("connection",function(socket){
setInterval(function(){
console.log("Server calling update collection with socket No.",socket.No);
},3000);
//When connection is close()
socket.on("disconnect",function(){
console.log("A user disconnected");
});
})
What happen is that, for example, I disconnect from the server, I find that server is still logging. What can I do so that I can stop it?
Thanks~
In the code above, it is setInterval that is causing the additional logging.
You will need to store off the id returned from setInterval then clear it using clearInterval on a disconnect event.
Something like:
io.sockets.on("connection",function(socket){
var intervalId = setInterval(function(){
console.log("Server calling update collection with socket No.",socket.No);
},3000);
//When connection is close()
socket.on("disconnect",function(){
console.log("A user disconnected");
clearInterval(intervalId);
});
})
Other than that, no need to do anything else with the socket on the server side. It will get garbage collected at some point.

Get connection status on Socket.io client

I'm using Socket.io, and I'd like to know the status of connection to the server from the client-side.
Something like this:
socket.status // return true if connected, false otherwise
I need this information to give a visual feedback to the user if the connection has dropped or it has disconnected for any reason.
You can check the socket.connected property:
var socket = io.connect();
console.log('check 1', socket.connected);
socket.on('connect', function() {
console.log('check 2', socket.connected);
});
It's updated dynamically, if the connection is lost it'll be set to false until the client picks up the connection again. So easy to check for with setInterval or something like that.
Another solution would be to catch disconnect events and track the status yourself.
You can check whether the connection was lost or not by using this function:-
var socket = io( /**connection**/ );
socket.on('disconnect', function(){
//Your Code Here
});
Hope it will help you.
These days, socket.on('connect', ...) is not working for me.
I use the below code to check at 1st connecting.
if (socket.connected)
console.log('socket.io is connected.')
and use this code when reconnected.
socket.on('reconnect', ()=>{
//Your Code Here
});
Track the state of the connection yourself. With a boolean. Set it to false at declaration. Use the various events (connect, disconnect, reconnect, etc.) to reassign the current boolean value. Note: Using undocumented API features (e.g., socket.connected), is not a good idea; the feature could get removed in a subsequent version without the removal being mentioned.
#robertklep's answer to check socket.connected is correct except for reconnect event, https://socket.io/docs/client-api/#event-reconnect
As the document said it is "Fired upon a successful reconnection." but when you check socket.connected then it is false.
Not sure it is a bug or intentional.

List of connected clients username using socket io

I've made a chat client with different chat rooms in NodeJS, socketIO and Express. I am trying to display an updated list over connected users for each room.
Is there a way to connect a username to an object so I could see all the usernames when I do:
var users = io.sockets.clients('room')
and then do something like this:
users[0].username
In what other ways can I do this?
Solved:
This is sort of a duplicate, but the solution is not written out very clearly anywhere so I'd thought I write it down here. This is the solution of the post by Andy Hin which was answered by mak. And also the comments in this post.
Just to make things a bit clearer. If you want to store anything on a socket object you can do this:
socket.set('nickname', 'Guest');
sockets also has a get method, so if you want all of the users do:
for (var socketId in io.sockets.sockets) {
io.sockets.sockets[socketId].get('nickname', function(err, nickname) {
console.log(nickname);
});
}
As alessioalex pointed out, the API might change and it is safer to keep track of user by yourself. You can do so this by using the socket id on disconnect.
io.sockets.on('connection', function (socket) {
socket.on('disconnect', function() {
console.log(socket.id + ' disconnected');
//remove user from db
}
});
There are similar questions that will help you with this:
Socket.IO - how do I get a list of connected sockets/clients?
Create a list of Connected Clients using socket.io
My advice is to keep track yourself of the list of connected clients, because you never know when the internal API of Socket.IO may change. So on each connect add the client to an array (or to the database) and on each disconnect remove him.
In socket.io#2.3.0 you can use:
Object.keys(io.sockets).forEach((socketId) => {
const socket = io.sockets[socketId];
})

Resources