Единый объект ввода-вывода сокета

#javascript #jquery #html #socket.io

#javascript #jquery #HTML #socket.io

Вопрос:

Я пытаюсь создать приложение на основе сокета. Глядя на консоль, можно сказать, что клиент дважды пытается подключиться к серверу сокетов; что не должно быть разрешено.

  1. Есть ли какой-нибудь способ остановить это?
  2. Если у вас есть модульный файл 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:

  1. Не подключайте клиент к сокету дважды….

  2. Глобальная переменная позволит вам получить доступ к сокету из всех ваших файлов скриптов

Например)

 //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 — Значит, вы НЕ включили НИ одну из этих фактических сведений в свой вопрос? Итак, как, черт возьми, вы ожидаете получить ответ на это? Серьезно, либо оцените ответы на то, что вы на самом деле указали в своем вопросе, либо в следующий раз задайте свой РЕАЛЬНЫЙ вопрос в своем вопросе. Мы здесь не читаем мысли. Я ответил именно на то, что вы указали в своем вопросе. Я показал вам, как запретить несколько подключений из одного браузера.