socket.io assigning custom socket.id
Solution 1
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
Solution 2
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);
...
}
LckySnday
Nothing special, just someone who want to learn something.
Updated on July 09, 2022Comments
-
LckySnday almost 2 years
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)
-
efkan about 7 yearsIf you need to complete this operation you might setting
generateId
prop ofio.eio
orio.engine
object. I've tried to explain over here stackoverflow.com/a/42483423/3765109
-
-
LckySnday about 8 yearsThanks for the answer, I do know overwriting socket.id may break some functionality, But if there is simple trick to fix my issue, then I will definitely go for it instead of re-design all the code.
-
user969068 almost 7 yearshow can we include custom id from socket-client
io.engine.generateId
? when we make connection from clientio.connect('ws://IP:PORT');
? -
efkan almost 7 yearsSetting a function to
io.engine.generateId
should be worked. Client is not important in this case and if I'm right 'ws' or 'https' is also not a subject. I guess you can manage it. -
user969068 almost 7 yearswhat I am trying to do is from client side when I make a connection it send a custom client id to make connection, there is no way to call
io.engine.generateId
from client side, I think I have to pass as query likeio.connect('ws://IP:PORT' {query: 'id=custom_id'});
, still trying to figure how can I assign thatcustom_id
as socket.id on server before connection is established -
efkan almost 7 yearsI'm sorry for my misunderstanding. You've been trying to give a client socket id value on client side. Unfortunately my answer doesn't provide that. Socket Id is given by Socket Server in Socket Server. Why you have to give an id in client side? Generally this operation is needed in server side to give a socket id from a current database (like user id).