SocketIO Identify what user disconnected
Solution 1
You could just store the id
value in the parent scope, which the disconnect
event handler would have access to:
io.on('connection', function(socket) {
var userId;
socket.on('new player', function(id, name) {
userId = id = parseInt(id);
// ...
});
socket.on('disconnect', function() {
delete playerList[userId];
});
};
Solution 2
Maybe I'm late to the party but I was stuck with something similar and found it the hard way and this may help someone.
The best way to detect if the user is disconnected is would be to first set the username in socket session.
Send the name from the client on emit
socket.emit("newUser", username);
and on server
socket.on('newUser',function (username) {
// we store the username in the socket session for this client
socket.username = username;
});
and when the user disconnects find that on the disconnect event
socket.on('disconnect', function () {
var connectionMessage = socket.username + " Disconnected from Socket " + socket.id;
console.log(connectionMessage);
});
and you can take it from there.
Solution 3
This worked for me:
On every new connection or user who comes online generate a socket Id, add it to the user object, and add it to the array of all the users online.
const users = [];
io.on('connection', (socket) => {
const socketId = socket.id;
socket.on('user online', (data) => {
users.push({ ...data, socketId });
io.emit('view user online', user);
});
Then in the disconnect
, use forEach
to loop through each object in the array, then use for
to loop through and delete
each key in the object:
socket.on('disconnect', () => {
users.forEach((user) => {
if (user.socketId === socket.id) {
for (const key in user) {
delete user[key];
}
}
});
logger(`A user has disconnected`);
});
});
});
Tweak to the way you want.
Weastie
Updated on June 14, 2022Comments
-
Weastie almost 2 years
I am making a simple Node.js game that uses Express, Socket.io, and an Http server. All of the users are stored in a multidimensional object on the server. This is how the server-side code works:
var express = require('express'); var app = express(); var http = require('http').Server(app); var io = require('socket.io')(http); app.use(express.static(__dirname + '/')); var playerList = {}; createPlayer = function(array,width,height,spdx,spdy,x,y,color,name,id) { var player = { width:width, height:height, spdx:spdx, spdy:spdy, x:x, y:y, wKeyDown:false, aKeyDown:false, sKeyDown:false, dKeyDown:false, color:color, name:name, id:id } array[id] = player; } io.on('connection', function(socket) { socket.on('new player', function(id, name) { id = parseInt(id); if (!playerList[id]) { createPlayer(playerList,25,25,4,4,Math.round(Math.random() * 800),Math.round(Math.random() * 600),randomColor(),name,id); } socket.on('pressW', function(id, keyDown) { playerList[id].wKeyDown = keyDown; }); socket.on('pressA', function(id, keyDown) { playerList[id].aKeyDown = keyDown; }); socket.on('pressS', function(id, keyDown) { playerList[id].sKeyDown = keyDown; }); socket.on('pressD', function(id, keyDown) { playerList[id].dKeyDown = keyDown; }); }); socket.on('disconnect', function() { }); }; sendPlayerList = function() { //newPlayerList is used to prevent client from seeing other users IDs var newPlayerList = {}; var count = 0; for (var q in playerList) { player = { x:playerList[q].x, y:playerList[q].y, width:playerList[q].width, height:playerList[q].height, color:playerList[q].color, name:playerList[q].name, } newPlayerList[count] = player; count++; } io.emit('edit playerlist', newPlayerList); } SPLInterval = setInterval(sendPlayerList, 1000);
Here is the client-side code for connection:
var id; $('#playbutton').click(function() { var name = document.getElementById('name').value; id = Math.floor(Date.now() * Math.random()); socket.emit('new player', id, name); });
On the client-side, in the update loop, when the game wants to tell the server your input, it emits your input like so:
update = function() { ctx.clearRect(0,0,canvas.width,canvas.height); if (document.hasFocus()) { socket.emit('pressD', id, dKeyDown); socket.emit('pressS', id, sKeyDown); socket.emit('pressA', id, aKeyDown); socket.emit('pressW', id, wKeyDown); }else{ socket.emit('pressD', id, false); socket.emit('pressS', id, false); socket.emit('pressA', id, false); socket.emit('pressW', id, false); } clientUpdatePlayer(); updatePlayers(); } } var updateInterval = setInterval(update, 31.25);
The function to update players just draws players based on the player list sent from the server.
My problem is that when a user disconnects, they stay in the player list. I don't understand how I should go about fixing this. I identify users by getting the ID they send from the client, but I can't get the user's id when they disconnect.
There is a lot more code, but I tried to only include the code that I thought was necessary. I am willing to include more code if that is needed.
-
Weastie almost 9 yearsWould that work for multiple users? Wouldn't that just change the userId variable to the most recent player who connected?
-
mscdex almost 9 yearsYes it would work for multiple users. You already have the correct scope from the
connection
event handler, so it's the same socket and thus the same user. So unless you have it such that a user can register multiple player names concurrently on the same socket, you should be ok. -
Mehdi Akbarian Rastaghi over 7 yearswhy its the correct answer?user A with id=1 connect to server and userId is 1 now after that userB with id=2 connect to server after userA and userId is 2!now if userA disconnect this callback will delete userB from playerList!!
-
Vikneshwar about 6 yearsI think userId will have the id of the user who joined recently.
-
Farbod Ahmadian almost 4 yearsPlease provide more information for further detail.
-
Anand Kumar Pandey almost 4 yearsFind the user which has disconnected using "socket.id" const presentUser = users.find(user => user.id == socket.id); Then remove this user from the list of online users using, users = users.filter(user => user != presentUser);
-
Anand Kumar Pandey almost 4 yearsHope you are OK with the "arrow function" and the "find" and "filter" array methods in javascript.
-
Anand Kumar Pandey almost 4 years
const presentUser = users.find(user => user.id == socket.id);
Here socket.id refers to the socket or client which triggered the disconnect event or the client which has disconnected. -
Drkawashima over 2 yearsUpvoted! Even if the answer posted by mscdex would work, I think it feels much more reliable and flexible to store the username on the socket-object and be able to get it from there at all times.