Отправить сообщение конкретному клиенту с сокетом.io и узел.Яш

Я работаю с сокетом.io и узел.JS и до сих пор это кажется довольно хорошим, но я не знаю как отправить сообщение от сервера к конкретному клиенту, что-то вроде этого:

client.send(message, receiverSessionId)

, но ни .send(), ни .broadcast() методы, похоже, удовлетворяют мою потребность.

что я нашел в качестве возможного решения, так это то, что .broadcast() метод принимает в качестве второго параметра массив с которым отправляется не отправить сообщение, поэтому я могу передать массив со всеми Которым отправляется подключено в данный момент к серверу, за исключением одного, я хочу отправить сообщение, но я чувствую, что там должно быть лучшее решение.

какие идеи?

11 ответов


Ну, вы должны захватить клиента для этого (сюрприз), вы можете либо пойти простым способом:

var io = io.listen(server);
io.clients[sessionID].send()

который может сломаться, я в этом почти не сомневаюсь, но всегда есть вероятность, что io.clients может измениться, поэтому используйте вышеизложенное с осторожностью

или вы сами отслеживаете клиентов, поэтому вы добавляете их в свой собственный


ответ Иво Ветцеля, похоже, не действителен в сокете.io 0.9 больше.

короче говоря, теперь вы должны сохранить socket.id и использовать io.sockets.socket(savedSocketId).emit(...) для отправки сообщений на него.

вот как я получил эту работу в кластерном узле.сервер js:

сначала вам нужно установить Redis store в качестве магазина, чтобы сообщения могли пересекать процессы:

var express = require("express");
var redis = require("redis");
var sio = require("socket.io");

var client = redis.createClient()
var app = express.createServer();
var io = sio.listen(app);

io.set("store", new sio.RedisStore);


// In this example we have one master client socket 
// that receives messages from others.

io.sockets.on('connection', function(socket) {

  // Promote this socket as master
  socket.on("I'm the master", function() {

    // Save the socket id to Redis so that all processes can access it.
    client.set("mastersocket", socket.id, function(err) {
      if (err) throw err;
      console.log("Master socket is now" + socket.id);
    });
  });

  socket.on("message to master", function(msg) {

    // Fetch the socket id from Redis
    client.get("mastersocket", function(err, socketId) {
      if (err) throw err;
      io.sockets.socket(socketId).emit(msg);
    });
  });

});

Я опустил код кластеризации здесь, потому что он делает это более загроможденным, но его тривиально добавить. Просто добавить все рабочий код. Больше документов здесь http://nodejs.org/api/cluster.html


каждый сокет присоединяется к комнате с идентификатором сокета имя, так что вы можете просто

io.to(socket#id).emit('hey')

docs:http://socket.io/docs/rooms-and-namespaces/#default-room

Ура


самое простое, самое элегантное решение

это так же просто, как:

client.emit("your message");

и это все.

но как? Приведите пример

то, что нам всем нужно, на самом деле является полным примером, и это то, что следует. Это проверено с самым последним сокетом.версия io (2.0.3), а также использует современный Javascript (который мы все должны использовать сейчас).

пример состоит из двух частей: сервера и клиента. Всякий раз, когда клиент подключается, он начинает получать от сервера периодический порядковый номер. Новая последовательность для каждого нового клиента, поэтому сервер должен отслеживать их по отдельности. Вот где "мне нужно отправить сообщение конкретному клиенту" вступает в игру. Код очень прост для понимания. Давайте посмотрим.

сервер

server.js

const
    io = require("socket.io"),
    server = io.listen(8000);

let
    sequenceNumberByClient = new Map();

// event fired every time a new client connects:
server.on("connection", (socket) => {
    console.info(`Client connected [id=${socket.id}]`);
    // initialize this client's sequence number
    sequenceNumberByClient.set(socket, 1);

    // when socket disconnects, remove it from the list:
    socket.on("disconnect", () => {
        sequenceNumberByClient.delete(socket);
        console.info(`Client gone [id=${socket.id}]`);
    });
});

// sends each client its current sequence number
setInterval(() => {
    for (const [client, sequenceNumber] of sequenceNumberByClient.entries()) {
        client.emit("seq-num", sequenceNumber);
        sequenceNumberByClient.set(client, sequenceNumber + 1);
    }
}, 1000);

сервер начинает слушать порт 8000 для входящих подключений. Когда один прибывает, он добавляет, что новый клиент на карту, чтобы он мог отслеживать его порядковый номер. Он также прослушивает disconnect событие, когда он удалит его с карты.

каждую секунду срабатывает таймер. Когда это происходит, сервер проходит по карте и отправляет сообщение каждому клиенту с его текущим порядковым номером. Тогда он увеличивает и хранит номер карты. В этом все дело. Проще простого.

клиент

в клиентская часть еще проще. Он просто подключается к серверу и слушает seq-num сообщение, печать его на консоль каждый раз, когда он прибывает.

client.js

const
    io = require("socket.io-client"),
    ioClient = io.connect("http://localhost:8000");

ioClient.on("seq-num", (msg) => console.info(msg));

выполнить пример

установите необходимые библиотеки:

npm install socket.io
npm install socket.io-client

запустить сервер:

node server

откройте другие окна терминала и породить столько клиентов, сколько вы хотите, запустив:

node client

я также подготовил суть с полный код здесь.


в 1.0, вы должны использовать:

io.sockets.connected[socketid].emit();

можно использовать

/ / отправить сообщение только отправителю-клиенту

socket.emit('message', 'check this');

/ / или вы можете отправить всем слушателям, включая отправителя

io.emit('message', 'check this');

/ / отправить всем слушателям, кроме отправителя

socket.broadcast.emit('message', 'this is a message');

//или вы можете отправить его в комнату

socket.broadcast.to('chatroom').emit('message', 'this is the message to all');


любая версия, которую мы используем, если мы просто консоль.log () объект" io", который мы используем в коде NodeJS на стороне сервера, [например, io.ВКЛ('connection', function(socket) {...});], мы можем видеть, что" io " - это просто объект json, и есть много дочерних объектов, где хранятся идентификатор сокета и объекты сокета.

Я использую сокет.io версия 1.3.5, кстати.

если мы посмотрим в объекте io, он содержит,

 sockets:
  { name: '/',
    server: [Circular],
    sockets: [ [Object], [Object] ],
    connected:
     { B5AC9w0sYmOGWe4fAAAA: [Object],
       'hWzf97fmU-TIwwzWAAAB': [Object] },

здесь мы можем увидеть socketids "B5AC9w0sYmOGWe4fAAAA" и т. д. Итак, мы можем сделать,

io.sockets.connected[socketid].emit();

опять же, при дальнейшем осмотре мы можем увидеть такие сегменты, как,

 eio:
  { clients:
     { B5AC9w0sYmOGWe4fAAAA: [Object],
       'hWzf97fmU-TIwwzWAAAB': [Object] },

Итак, мы можем получить сокет отсюда, выполнив

io.eio.clients[socketid].emit();

кроме того, под двигателем у нас есть,

engine:
 { clients:
    { B5AC9w0sYmOGWe4fAAAA: [Object],
      'hWzf97fmU-TIwwzWAAAB': [Object] },

Итак, мы можем записать,

io.engine.clients[socketid].emit();

Итак, я думаю, мы можем достичь нашей цели любым из 3 способов, перечисленных выше,

  1. io.розетки.подключен[socketid].испускают(); Или
  2. io.Эйо.клиенты[socketid].испускают(); Или
  3. io.двигатель.клиенты[socketid].emit ();

Вы можете сделать это

на сервере.

global.io=require("socket.io")(server);

io.on("connection",function(client){
    console.log("client is ",client.id);
    //This is handle by current connected client 
    client.emit('messages',{hello:'world'})
    //This is handle by every client
    io.sockets.emit("data",{data:"This is handle by every client"})
    app1.saveSession(client.id)

    client.on("disconnect",function(){
        app1.deleteSession(client.id)
        console.log("client disconnected",client.id);
    })

})

    //And this is handle by particular client 
    var socketId=req.query.id
    if(io.sockets.connected[socketId]!=null) {
        io.sockets.connected[socketId].emit('particular User', {data: "Event response by particular user "});
    }

и на клиенте, очень легко отрегулировать.

var socket=io.connect("http://localhost:8080/")
    socket.on("messages",function(data){
        console.log("message is ",data);
        //alert(data)
    })
    socket.on("data",function(data){
        console.log("data is ",data);
        //alert(data)
    })

    socket.on("particular User",function(data){
        console.log("data from server ",data);
        //alert(data)
    })

начиная с версии 1.4.5, убедитесь, что вы предоставили правильный префикс socketId в io.to (). Я брал socketId, который клиент вошел в систему для отладки, и он был без префикса, поэтому я закончил поиск навсегда, пока не узнал! Поэтому вам, возможно, придется сделать это так, если Id у вас нет префикса:

io.to('/#' + socketId).emit('myevent', {foo: 'bar'});

io.розетки.розетки[socket.id].emit (...) работал на меня в v0.9


гнездо.IO позволяет вам "пространство имен" ваших сокетов, что по существу означает назначение разных конечных точек или путей.

Это может помочь: http://socket.io/docs/rooms-and-namespaces/