我正在使用插座。io和node.js,到目前为止,它似乎很好,但我不知道如何从服务器发送消息到特定的客户端,就像这样:

client.send(message, receiverSessionId)

但是.send()和.broadcast()方法似乎都不能满足我的需要。

我发现了一个可能的解决方案,是.broadcast()方法接受作为第二个参数的sessionid数组,不发送消息,所以我可以传递一个数组与所有的sessionid连接到服务器,除了一个我希望发送消息,但我觉得必须有一个更好的解决方案。

什么好主意吗?


当前回答

最简单、最优雅的方式

验证与插座工作。io v3.1.1

很简单:

client.emit("your message");

就是这样。好吧,但是它是如何工作的呢?

最小工作示例

下面是一个简单的客户机-服务器交互示例,其中每个客户机定期接收包含序列号的消息。每个客户端都有一个唯一的序列,这就是“我需要向特定的客户端发送消息”发挥作用的地方。

服务器

server.js

const
    {Server} = require("socket.io"),
    server = new Server(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上监听传入的连接。一旦建立了新的连接,该客户端就被添加到跟踪其序列号的映射中。服务器还侦听断开连接事件,以便在客户端离开映射时将其从映射中删除。

每一秒,都会触发一个计时器。当它这样做时,服务器遍历映射,并向每个客户端发送带有当前序列号的消息,然后立即增加它。这就是它的全部。容易peasy。

客户端

客户端部分甚至更简单。它只是连接到服务器并侦听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@3.1.1 socket.io-client@3.1.1

运行服务器:

node server

打开其他终端窗口,运行以下命令生成任意数量的客户端:

node client

我还准备了一个要点与完整的代码在这里。

其他回答

不管我们使用的是什么版本,如果我们只是console.log()我们在服务器端nodejs代码中使用的“io”对象,[例如io. log]在('connection', function(socket){…});]上,我们可以看到"io"只是一个json对象,有许多子对象存储套接字id和套接字对象。

我正在使用socket。顺便说一句,IO版本1.3.5。

如果我们查看io对象,它包含,

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

在这里我们可以看到套接字“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();

所以,我想我们可以用上面列出的三种方法中的任何一种来实现我们的目标,

io.sockets.connected [socketid] .emit (); 或 io.eio.clients [socketid] .emit (); 或 io.engine.clients [socketid] .emit ();

好吧,你必须抓住客户(惊喜),你可以选择简单的方法:

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

它可能会坏,我怀疑,但总是有可能io。客户端可能会被更改,因此请谨慎使用上述方法

或者您自己跟踪客户端,因此您将它们添加到连接侦听器中自己的客户端对象中,并在断开连接侦听器中删除它们。

我将使用后者,因为根据应用程序的不同,您可能希望在客户机上有更多的状态,因此可以使用类似clients[id] = {conn: clientConnect, data:{…}}可能会起作用。

Ivo Wetzel的答案在Socket中似乎不成立。IO 0.9。

简而言之,现在必须保存套接字。使用io.sockets.socket(savedSocketId).emit(…)向它发送消息。

这是我如何在集群Node.js服务器中工作的:

首先,你需要设置Redis存储为存储,以便消息可以跨进程:

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

每个套接字用套接字id作为名称连接一个房间,所以您可以

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

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

Io.sockets.sockets [socket.id].emit(…)在v0.9中为我工作