Очевидное предложение состоит в том, чтобы остановить подключение вашего клиента дважды.
Но если вы пытаетесь предотвратить несколько подключений на сервере, и вы действительно не хотите, чтобы какой-либо конечный пользователь мог использовать несколько окон за раз на вашем веб-сайте, тогда вы можете предотвратить другое когда соединение уже установлено.
Ключ должен идентифицировать каждый браузер с каким-то уникальным cookie (идентификатором пользователя или уникально сгенерированным идентификационным номером). Затем вы можете реализовать аутентификацию socket.io, которая отслеживает, какие идентификаторы пользователей уже имеют соединение, и если соединение уже работает, последующие попытки подключения не пройдут этап аутентификации и будут отключены.
Предполагается, что у вас есть набор файлов cookie для каждого браузера, который называется userId
. Тогда, вот пример приложения, которое удостоверяется идента печенье присутствует, а затем использует его, чтобы запретить подключение более чем один socket.io:
const express = require('express');
const app = express();
const cookieParser = require('cookie-parser');
const cookie = require('cookie');
app.use(cookieParser());
let userIdCntr = 1;
const tenDays = 1000 * 3600 * 24 * 10;
app.use(function(req, res, next) {
// make sure there's always a userId cookie
if (!req.cookies || !req.cookies.userId) {
// coin unique user ID which consists of increasing counter and current time
let userId = userIdCntr++ + "_" + Date.now();
console.log("coining userId: " + userId);
res.cookie('userId', userId, { maxAge: Date.now() + tenDays , httpOnly: true });
}
next();
});
app.get('/test.html', function (req, res) {
console.log('Cookies: ', req.cookies)
res.sendFile(__dirname + "/" + "test.html");
});
const server = app.listen(80);
const io = require('socket.io')(server);
// which users are currently connected
var users = new Set();
// make sure cookie is parsed
io.use(function(socket, next) {
if (!socket.handshake.headers.cookieParsed) {
socket.handshake.headers.cookieParsed = cookie.parse(socket.handshake.headers.cookie || "");
}
next();
});
// now do auth to fail duplicate connections
io.use(function(socket, next) {
console.log("io.use() - auth");
// if no userId present, fail the auth
let userId = socket.handshake.headers.cookieParsed.userId;
if (!userId) {
next(new Error('Authentication error - no userId'));
return;
}
// if already logged in
if (users.has(userId)) {
console.log("Failing user " + userId);
next(new Error('Authentication error - duplicate connection for this userId'));
return;
} else {
console.log("adding user " + userId);
users.add(userId);
}
next();
});
io.on('connection', function(socket) {
console.log("socket.io connection cookies: ", socket.handshake.headers.cookieParsed);
socket.on('disconnect', function() {
console.log("socket.io disconnect");
let userId = socket.handshake.headers.cookieParsed.userId;
users.delete(userId);
});
// test message just to see if we're connected
socket.on("buttonSend", function(data) {
console.log("buttonSend: ", data);
});
});
P.S. Вам действительно нужно подумать о ситуации, когда пользователь с несколькими компьютерами (например, домашний/рабочий) оставляет один компьютер и открывает вашу страницу и, таким образом, подключается через socket.io, а затем пытается подключить ваш сайт с другого компьютера. Если вы отказались от второго соединения, это не позволит им получить доступ со своего второго компьютера, если первый компьютер оказался открытым и включенным.
поэтому решение приходит, чтобы создать фабрику, которая будет синглтон для io .. если не ошибаюсь – Rastafari