webSocketServer node.js如何区分客户端

Ajo*_*uve 54 websocket node.js

我试图使用node.js的套接字,我成功但我不知道如何区分我的代码中的客户端.关于套接字的部分是这样的:

var WebSocketServer = require('ws').Server, 
    wss = new WebSocketServer({port: 8080});
wss.on('connection', function(ws) {
    ws.on('message', function(message) {
        console.log('received: %s', message); 
        ws.send(message);
    });
    ws.send('something');
});
Run Code Online (Sandbox Code Playgroud)

这段代码适用于我的客户端js.

但我想向特定用户或在我的服务器上打开套接字的所有用户发送消息.

在我的情况下,我作为客户端发送消息,我收到响应,但其他用户没有显示任何内容.

我想例如user1通过webSocket向服务器发送消息,并向打开套接字的用户2发送通知.

Jza*_*ata 53

在nodejs中,您可以直接修改ws客户端并分别为每个客户端添加自定义属性.你还有一个全局变量wss.clients,可以在任何地方使用.请尝试下一个代码并尝试连接两个客户端:

var WebSocketServer = require('ws').Server;
var wss = new WebSocketServer({
    server: httpsServer
});


wss.getUniqueID = function () {
    function s4() {
        return Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);
    }
    return s4() + s4() + '-' + s4();
};

wss.on('connection', function connection(ws, req) {
    ws.id = wss.getUniqueID();

    wss.clients.forEach(function each(client) {
        console.log('Client.ID: ' + client.id);
    });
});
Run Code Online (Sandbox Code Playgroud)

您还可以直接在客户端连接URL中传递参数:

https://myhost:8080?myCustomParam=1111&myCustomID=2222

在连接函数中,您可以获取这些参数并将这些参数直接分配给您的ws客户端:

wss.on('connection', function connection(ws, req) {

    const parameters = url.parse(req.url, true);

    ws.uid = wss.getUniqueID();
    ws.chatRoom = {uid: parameters.query.myCustomID};
    ws.hereMyCustomParameter = parameters.query.myCustomParam;
}
Run Code Online (Sandbox Code Playgroud)

  • 为什么在任何地方都没有提及?好答案。 (2认同)
  • 答案+1。添加支持它的参考:https://github.com/websockets/ws/issues/859 (2认同)

Ank*_*sht 47

您只需将用户ID分配给数组CLIENTS [],这将包含所有用户.您可以直接向所有用户发送消息,如下所示:

var WebSocketServer = require('ws').Server,
    wss = new WebSocketServer({port: 8080}),
    CLIENTS=[];

wss.on('connection', function(ws) {
    CLIENTS.push(ws);
    ws.on('message', function(message) {
        console.log('received: %s', message);
        sendAll(message);
    });
    ws.send("NEW USER JOINED");
});

function sendAll (message) {
    for (var i=0; i<CLIENTS.length; i++) {
        CLIENTS[i].send("Message: " + message);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 此解决方案无法扩展,因为变量CLIENTS位于NodeJS的单个进程中.即使我们通过分支多个进程来利用多个核心,CLIENTS也不是共享内存分配,每个进程都维护自己的CLIENTS列表.因此,它需要后续连接与同一进程通信. (24认同)
  • @KhanhHua,请您提供可扩展的解决方案 (8认同)
  • 您可以使用Redis pub-sub并创建一个"发布"通道,您可以监听每个服务器.每当在该频道上发布消息时,每个服务器都会向其所有客户端广播.就那么简单. (5认同)
  • 根据[文档](https://github.com/websockets/ws/blob/master/doc/ws.md),`WebSocketServer`有一个`clients`属性,可以为您跟踪当前客户端.文档还给出了迭代该集合以向每个客户端发送广播消息的示例. (3认同)

H D*_*Dog 8

Worlize服务器中的这段代码片段对我帮助很大.即使您使用的是ws,代码也应该很容易适应.我在这里选择了重要的部分:

// initialization
var connections = {};
var connectionIDCounter = 0;

// when handling a new connection
connection.id = connectionIDCounter ++;
connections[connection.id] = connection;
// in your case you would rewrite these 2 lines as
ws.id = connectionIDCounter ++;
connections[ws.id] = ws;

// when a connection is closed
delete connections[connection.id];
// in your case you would rewrite this line as
delete connections[ws.id];
Run Code Online (Sandbox Code Playgroud)

现在您可以轻松创建一个broadcast()和sendToConnectionId()函数,如链接代码所示.

希望有所帮助.

  • 需要使用 `for in` 循环来进行广播,而不是标准的 for 循环,因为(关联)数组中存在“漏洞”。 (2认同)

dro*_*lla 8

这取决于您使用的websocket.例如,最快的一个,可以在这里找到:https://github.com/websockets/ws可以通过这种方法进行广播:

var WebSocketServer = require('ws').Server,
   wss = new WebSocketServer({host:'xxxx',port:xxxx}),
   users = [];
wss.broadcast = function broadcast(data) {
wss.clients.forEach(function each(client) {
  client.send(data);
 });
};
Run Code Online (Sandbox Code Playgroud)

然后在你的代码中你可以使用wss.broadcast(message)发送给所有人.要将PM发送给单个用户,请执行以下操作:

(1)在我发送给服务器的消息中,我包含了一个用户名(2)然后,在onMessage中,我使用该用户名将websocket保存在数组中,然后通过用户名检索它:

wss.on('connection', function(ws) {

  ws.on('message', function(message) {

      users[message.userName] = ws;
Run Code Online (Sandbox Code Playgroud)

(3)要发送给特定用户,您可以执行用户[userName] .send(message);


Kla*_*und 6

我正在使用 ws 对象中的 fd 。每个客户应该是唯一的。

var clientID = ws._socket._handle.fd;
Run Code Online (Sandbox Code Playgroud)

当我打开新的浏览器选项卡时,我得到了不同的号码。

第一个 ws 有 11 个,第二个有 12 个。

  • 我认为如果一个用户离开而另一个用户加入,文件描述符 fd 可以被重用......本质上它们可能会被回收 (13认同)

Ser*_*tes 5

您可以使用请求标头“ sec-websocket-key”

wss.on('connection', (ws, req) => {
  ws.id = req.headers['sec-websocket-key']; 

  //statements...
});
Run Code Online (Sandbox Code Playgroud)