#node.js #socket.io
#node.js #socket.io
Вопрос:
Эй, ребята, пожалуйста, мне нужна помощь в отправке данных конкретному пользователю в определенной комнате с помощью socket.io я использую redis для хранения идентификаторов администратора, который создал группу, но как мне получить идентификатор пользователя от redis и передать им в их комнате
мой код
const users = {}
const admins = {}
io.on('connection',socket =>{
socket.on('create-class',(address,userID)=>{
client.hmset(`${userID}`, `id`, `${userID}`);
})
socket.on('join-class',(classId,palsid)=>{
socket.join(classId)
client.hgetall(`${palsid}`, function(err, object) {
if(err)throw err
if(object !==null){
admins[socket.id] = object.id
}
socket.to(classId).broadcast.emit('user-connected',palsid)
});
//on disconnection
socket.on('disconnect',()=>{
socket.to(classId).broadcast.emit('user-disconnect',palsid)
})
})
Комментарии:
1. Можете ли вы добавить немного больше своего кода? Отправка в один конкретный сокет должна быть довольно простой и не зависеть от того, в какой комнате он находится.
2. Опять же, если вы хотите передать что-то в один конкретный сокет, не имеет значения, в какой комнате это находится. Что вы пытаетесь передать одному пользователю? И когда?
Ответ №1:
Основываясь на информации, которую предлагает OP, я могу дать только несколько советов.
Сначала вам нужно получить сокет (конкретного пользователя), в идеале по его идентификатору.
const socket = io.sockets.connected[socketid];
Затем вы просто отправляете в этот сокет
socket.emit("message", "hello world");
Это должно отправить сообщение одному конкретному сокету (пользователю), независимо от того, в какой комнате он находится. Это все еще оставляет вопрос о том, где получить идентификатор socketid, но для ответа на него нам нужна дополнительная информация о вашем коде / настройке / приложении. Обычно идентификаторы сокетов хранятся в каком-то хранилище / базе данных или памяти.
Сохраняйте ссылку на идентификатор сокета
Теперь идентификатор сокета является чем-то временным. Всякий раз, когда подключается сокет, он получает другой идентификатор сокета. Как можно идентифицировать одного конкретного пользователя для любого сокета, если идентификатор сокета является временным?
A: сохраните ссылку на идентификатор сокета, используя что-то временное
Когда пользователь подключается к серверу websocket, есть шанс, что он / она делает это вместе с уникальным идентификатором пользователя. Если у вас есть база данных пользователей, все они имеют уникальный идентификатор (обычно). Сохраняйте этот идентификатор вместе с идентификатором socketid при подключении сокета, и вы будете ссылаться на сокет в любой более поздний момент времени, используя уникальный идентификатор пользователя. Существуют разные способы передачи длинного идентификатора пользователя при подключении сокета: вы можете использовать токен запроса, например :
// client side
const ioClient = require('socket.io-client');
ioClient(url '/?token=aaaabbbbccccdddd');
// server side
io.on('connection', function(socket) {
const userid = socket.handshake.query.token; // aaaabbbbccccdddd
inMemoryStore.sockets[userid] = socket.id;
});
B: используйте временный идентификатор в качестве идентификатора сокета
Существует также возможность установить свой собственный идентификатор socketid для каждого сокета. Таким образом, вы можете напрямую использовать идентификатор пользователя или любой другой временный идентификатор в качестве идентификатора сокета. Что-то вроде этого :
// server side
io.engine.generateId = (req) => {
return req.query.token;
}
Комментарии:
1. Ну, я пытаюсь создать приложение webrtc, и мне нужен сценарий, в котором администратор может получать поток всех пользователей, которые подключены в этой группе, но все пользователи получают только поток администратора, например, одноранговое соединение «один ко многим»
2. Теперь моя проблема в том, как мне получить I’d из redis, сохранить его, а затем передать этому администратору в определенной комнате, если там более одной комнаты, потому что, если есть более одной комнаты, это означает, что в redis хранится более одного администратора
3. Извините, мне все еще не на 100% ясно, чего вы пытаетесь достичь. Мне кажется, это скорее «структурная» проблема. Если у вас есть идентификатор любого сокета, вы можете просто передавать только этому сокету, используя приведенный выше код. Я предполагаю, что вы сохраняете все идентификаторы сокетов (при их подключении) под ссылочным идентификатором (который никогда не меняется, например, идентификатор пользователя или аналогичный), поэтому вы никогда не теряете ссылку на идентификатор сокета. Sry на данный момент я не могу вам больше помочь.
4. Я обновил свой ответ, возможно, я получил правильное направление
5. @princerandy вы хотите показать, что вы сделали в итоге? Или мой ответ вам помог? (если это так, пожалуйста, примите это как правильный ответ)
Ответ №2:
прежде всего, я не знал, что при обновлении страницы идентификатор сокета изменяется, поэтому я сделал кнопку на интерфейсе, которая отправляет сигнал на сервер, идентифицируя пользователя как администратора сервер сохраняет идентификатор сокета в redis, когда любой пользователь присоединяется к этой конкретной комнате, сервер просто извлекает этот идентификатор администратора и отправляет пользователю, подключающемуся, позволяя им делиться своим потоком. затем с помощью io.to (socketId).emit(‘user-connected’, palsid); для отправки обратно только в сокет администратора. таким образом, любой пользователь, который подключается к этой комнате, поток отправляется только администратору, а не всем остальным в комнате, что делает видеоконференцию «один ко многим»
мой внешний код
//for button
<Button onClick={this.setAdmin}>send stream</Button>
the function
setAdmin=()=>{
console.log(socket.id)
socket.emit('create-class',this.props.match.id,socket.id)
}
мой внутренний код
io.on('connection',socket =>{
socket.on('create-class',(address,socketID)=>{
//save to redis so all client can connect to this socket
client.set("adminsocket",socketID,(err)=>{
if(err)throw err;
})
})
socket.on('join-class',async(classId,palsid)=>{
socket.join(classId)
//Fetch the socket.id from redis
client.get("adminsocket",(err,socketID)=>{
if(err) throw err
io.to(socketID).emit('user-connected', palsid);
})
//on disconnection
socket.on('disconnect',()=>{
socket.to(classId).broadcast.emit('user-disconnect',palsid)
})
})