I keep track the list of every users connected in the array.
So if there is a new connection, it will check whether the user is already on the list or not, if he was already on the list, then assign their socket.id with the corresponding socket.id on the list, otherwise just add them to the list.
It's for preventing same user counted as 2 user while he attempt to do multi-login.
Object.keys(client).forEach(function (key) {
if (client[key].id == data.id){
is_connected = true;
socket.id = key;
}
});
I have no problem handling the messages/chat that was sent/received by the user who attempt multi-login.
socket.on('chat', function(msg){
var data = {"name": client[socket.id].name, "message": msg};
io.emit('chat', data);
});
The io.emit for the chat message was succesfully sent to the user who attempting multi-login.
The problem I got was whenever the user decide to logout/disconnect from the server.
io.emit('user_leave', client[socket.id].id);
[Multi-Login Case] -> Multi-User and Dual-User are same user attempting Multi-Login
Whenever the Main-User disconnected from the server, the Dual-User received 'user_leave' sent by the server, because io.emit supposed to send it to all sockets.
But not otherwise, while the Sub-User disconnected from the server, the Main-user do not receive 'user_leave' emitted by the server.
*Note: Main-User is login first, then the Dual-User. So the Main-User information was saved directly in the array, while the Sub-User socket.id was assigned with the Main-User socket.id
[Update]
B2 socket.id was assigned with B1 socket.id, the io.emit for chat work perfectly while io.emit for disconnect only emitted to All except Dual-User(B2)
socket.id
is used internally by socket.io for its own socket list. You cannot overwrite that or you break some of its ability to maintain its own data structures.
You have two choices:
- You can use the existing
socket.id
value as is (without overwriting it) so you don't break existing behavior. It is already guaranteed to be unique on the server.
- You can use a different property name for your own id such as
socket.userId
and then you won't conflict.
If you need to, you can maintain a map between your own custom id and the socket.io socket.id
so you could get to one from the other.
Similar question here: Socket.io custom client ID
generateId prop of io.engine
object can be used for to set the custom id.
Using this way, the all socket ids can be created on the server side without any issue.
Actually I wrote an answer for a similar question today.
An example:
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
io.engine.generateId = function (req) {
// generate a new custom id here
return 1
}
io.on('connection', function (socket) {
// listing the default namespace rooms
console.log("rooms: ", io.nsps["/"].adapter.rooms);
})
The console output would be as the following:
rooms: { '/#1': Room { sockets: { '/#1': true }, length: 1 } }
It seems to be it has been handled.
It must be in mind that socket id must be unpredictable and unique value with considering security and the app operations!
Extra: If socket.id
is returned as undefined
because of your intense processes on your generateId
method, async/await
combination can be used to overcome this issue on node.js
version 7.6.0 and later.
handshake
method of node_modules/engine.io/lib/server.js
file should be changed as following:
former:
Server.prototype.handshake = function (transportName, req) {
var id = this.generateId(req);
...
}
new:
Server.prototype.handshake = async function (transportName, req) {
var id = await this.generateId(req);
...
}