#javascript #jquery #html #socket.io
#javascript #jquery #HTML #socket.io
Вопрос:
Я пытаюсь создать приложение на основе сокета. Глядя на консоль, можно сказать, что клиент дважды пытается подключиться к серверу сокетов; что не должно быть разрешено.
- Есть ли какой-нибудь способ остановить это?
- Если у вас есть модульный файл javascript, в котором несколько сценариев хотят получить доступ к одному и тому же соединению с сокетом, как это возможно?
<!DOCTYPE html>
<html>
<head>
<title>socket</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="https://cdn.socket.io/socket.io-1.4.5.js"></script>
</head>
<body>
<script type="text/javascript">
$(function(){
var socket = io();
console.log(typeof socket); // object
var socket1 = io();
console.log(socket === socket1); // false
})
</script>
</body>
</html>
Ответ №1:
-
Не подключайте клиент к сокету дважды….
-
Глобальная переменная позволит вам получить доступ к сокету из всех ваших файлов скриптов
Например)
//you can access this variable from all your scripts
var socket;
$(function(){
socket = io();
console.log(typeof socket);
})
Обратите внимание, что в javascript загрязнение глобальной области видимости переменными и функциями считается плохой практикой, но это для другого поста.
Комментарии:
1. итак, решение заключается в создании фабрики, которая будет использовать синглтон для ввода-вывода.. если я не ошибаюсь
Ответ №2:
Очевидное предложение состоит в том, чтобы перестать подключать ваш клиент дважды.
Но, если вы пытаетесь предотвратить несколько подключений на сервере, и вы действительно не хотите, чтобы какой-либо конечный пользователь мог использовать более одного окна одновременно на вашем веб-сайте, тогда вы можете предотвратить другое подключение, когда соединение уже есть.
Ключом было бы идентифицировать каждый браузер с помощью какого-либо уникального файла cookie (идентификатор пользователя или уникально сгенерированный идентификационный номер). Затем вы можете реализовать сокет.аутентификация ввода-вывода, которая отслеживает, какие идентификаторы пользователей уже имеют соединение, и если соединение уже установлено, то последующие попытки подключения завершатся ошибкой этапа аутентификации и будут отключены.
Предполагается, что у вас есть набор файлов cookie для каждого вызываемого браузера userId
. Затем, вот пример приложения, которое проверяет наличие cookie идентификатора пользователя, а затем использует его для запрета более одного сокета.подключение ввода-вывода:
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);
});
});
PS Вам действительно нужно продумать ситуацию, когда пользователь с более чем одним компьютером (например, дома / на работе) оставляет один компьютер включенным и открытым для вашей страницы и, таким образом, подключается через сокет.ввод-вывод, а затем пытается использовать ваш сайт с другого компьютера. Если вы отказались от второго подключения, это откажет им в доступе со своего второго компьютера, если первый компьютер оказался открытым и включенным.
Комментарии:
1. Добавлен пример кода, который запрещает более одного сокета. подключение ввода-вывода для каждого браузера.
2. На самом деле, если у меня есть структура плагинов компонентов представления, в которой два или более плагинов хотят получить доступ к службе сокетов, тогда, если сокет уже подключен, я хочу использовать существующее соединение, иначе я хочу создать новое соединение.
3. @Rastafari — Значит, вы НЕ включили НИ одну из этих фактических сведений в свой вопрос? Итак, как, черт возьми, вы ожидаете получить ответ на это? Серьезно, либо оцените ответы на то, что вы на самом деле указали в своем вопросе, либо в следующий раз задайте свой РЕАЛЬНЫЙ вопрос в своем вопросе. Мы здесь не читаем мысли. Я ответил именно на то, что вы указали в своем вопросе. Я показал вам, как запретить несколько подключений из одного браузера.