Socket.io custom client ID
I'm making a chat app with socket.io, and I'd like to use my custom client id, instead of the default ones (8411473621394412707
, 1120516437992682114
). Is the开发者_开发百科re any ways of sending the custom identifier when connecting or just using something to track a custom name for each ID? Thanks!
You can create an array on the server, and store custom objects on it. For example, you could store the id created by Socket.io and a custom ID sent by each client to the server:
var util = require("util"),
io = require('/socket.io').listen(8080),
fs = require('fs'),
os = require('os'),
url = require('url');
var clients =[];
io.sockets.on('connection', function (socket) {
socket.on('storeClientInfo', function (data) {
var clientInfo = new Object();
clientInfo.customId = data.customId;
clientInfo.clientId = socket.id;
clients.push(clientInfo);
});
socket.on('disconnect', function (data) {
for( var i=0, len=clients.length; i<len; ++i ){
var c = clients[i];
if(c.clientId == socket.id){
clients.splice(i,1);
break;
}
}
});
});
in this example, you need to call storeClientInfo from each client.
<script>
var socket = io.connect('http://localhost', {port: 8080});
socket.on('connect', function (data) {
socket.emit('storeClientInfo', { customId:"000CustomIdHere0000" });
});
</script>
Hope this helps.
To set custom socket id, generateId function must be overwritten. Both of eio
and engine
props of Socket.io
server object can be used for to manage this operation.
A simple 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) {
console.log(socket.id); // writes 1 on the console
})
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:
current:
// engine.io/lib/server.js
Server.prototype.generateId = function (req) {
return base64id.generateId();
};
Server.prototype.handshake = function (transportName, req) {
var id = this.generateId(req);
...
}
new:
// function assignment
io.engine.generateId = function (req) {
return new Promise(function (resolve, reject) {
let id;
// some intense id generation processes
// ...
resolve(id);
});
};
// engine.io/lib/server.js
Server.prototype.handshake = async function (transportName, req) {
var id = await this.generateId(req);
...
}
Note: At Engine.io v4.0, generateId
method would accept a callback. So it would not needed to change handshake
method. Only generateId
method replacement is going to be enough. For instance:
io.engine.generateId = function (req, callback) {
// some intense id generation processes
// ...
callback(id);
};
In the newest socket.io (version 1.x) you can do something like this
socket = io.connect('http://localhost');
socket.on('connect', function() {
console.log(socket.io.engine.id); // old ID
socket.io.engine.id = 'new ID';
console.log(socket.io.engine.id); // new ID
});
I would use an object as a hash lookup - this will save you looping through an array
var clients = {};
clients[customId] = clientId;
var lookup = clients[customId];
Do not change the socket IDs to ones of your own choosing, it breaks the Socket.io room system entirely. It will fail silently and you'll have no clue why your clients aren't receiving the messages.
This will work with 2.2.0 and above version of Socket.IO
To set custom Socket Id, generateId
function must be overwritten.
A simple example:
Server Side
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
io.use((socket, next) => {
io.engine.generateId = () => {
// USE ONE OF THESE
socket.handshake.query.CustomId; // this work for me
// return socket.handshake.query.CustomId;
}
next(null, true);
});
io.on('connection', function (socket) {
console.log(socket.id);
})
Clint Side
io.connect(URL, { query: "CustomId = CUSTOM ID IS HERE" })
NOTE: Keep in mind that socket id must be a unique value.
why not a simpler solution that does not need to maintain an array of connected clients and does not override internal socket id?
io.on("connection", (socket) => {
socket.on('storeClientInfo', (data) => {
console.log("connected custom id:", data.customId);
socket.customId = data.customId;
});
socket.on("disconnect", () => {
console.log("disconnected custom id:", socket.customId);
})
});
Client side
let customId = "your_custom_device_id";
socket.on("connect", () => {
socket.emit('storeClientInfo', { customId: customId });
});
or you can override the socket id, like this:
io.on('connection', function(socket){
socket.id = "YOUR_CUSTOM_ID";
});
you can see under the array:
io.sockets.sockets
Can store customId (example userId) in object format instead of for loop, this will improve performance during connection, disconnect and retrieving socketId for emitting
`
var userId_SocketId_KeyPair = {};
var socketId_UserId_KeyPair = {};
_io.on('connection', (socket) => {
console.log('Client connected');
//On socket disconnect
socket.on('disconnect', () => {
// Removing sockets
let socketId = socket.id;
let userId = socketId_UserId_KeyPair[socketId];
delete socketId_UserId_KeyPair[socketId];
if (userId != undefined) {
delete userId_SocketId_KeyPair[userId];
}
console.log("onDisconnect deleted socket with userId :" + "\nUserId,socketId :" + userId + "," + socketId);
});
//Store client info
socket.on('storeClientInfo', function (data) {
let jsonObject = JSON.parse(data);
let userId = jsonObject.userId;
let socketId = socket.id;
userId_SocketId_KeyPair[userId] = socketId;
socketId_UserId_KeyPair[socketId] = userId;
console.log("storeClientInfo called with :" + data + "\nUserId,socketId :" + userId + "," + socketId);
});
`
With this 2.2.0 version of Socket.IO, you can achieve this.
io.use((socket, next) => {
io.engine.generateId = () => socket.handshake.query.token;
next(null, true);
});
If you are trying to use a custom id to in order to communicate with a specific client then you can do this
io.on('connection', function(socket){
socket.id = "someId"
io.sockets.connected["someId"] = io.sockets.connected[socket.id];
// them emit to it by id like this
io.sockets.connected["someId"].emit("some message", "message content")
});
精彩评论