使用webSocket向特定的已连接用户发送消息?

Roy*_*mir 68 javascript html5 websocket node.js

我写了一个代码,用于向所有用户广播消息:

二手代码:( 简要)

// websocket and http servers
var webSocketServer = require('websocket').server;

...
...
var clients = [ ];

var server = http.createServer(function(request, response) {
    // Not important for us. We're writing WebSocket server, not HTTP server
});
server.listen(webSocketsServerPort, function() {
  ...
});

var wsServer = new webSocketServer({
    // WebSocket server is tied to a HTTP server. 
    httpServer: server
});


    // This callback function is called every time someone
    // tries to connect to the WebSocket server
    wsServer.on('request', function(request) {
    ...
    var connection = request.accept(null, request.origin); 
    var index = clients.push(connection) - 1;
    ...
Run Code Online (Sandbox Code Playgroud)

请注意 :

  • 我没有任何用户参考,只有一个连接.
  • 所有用户连接都存储在array.

目标:假设NodeJs服务器想要向特定客户端(John)发送消息.

这是一个问题:

  • NodeJs服务器如何知道John有哪个连接?

    NodeJs服务器甚至不知道John.所有它看到的是连接.

所以,我相信现在,我不应该只通过他们的连接来存储用户,而是需要存储一个对象 - 它将包含对象userIdconnection对象.

这是我的想法:


  • 当页面完成加载(Dom ready) - 建立与NodeJs服务器的连接.

  • 当NodeJs服务器接受连接时 - 生成唯一的字符串并将其发送到客户端浏览器.将用户连接和唯一字符串存储在对象中.例如 {UserID:"6" , value :{connectionObject}}

  • 在客户端,当此消息到达时 - 将其存储在隐藏字段或cookie中.(用于将来对NodeJs服务器的请求)


当服务器想要向John发送消息时:

  • 在字典中查找john的UserID并通过相应的连接发送消息.

请注意这里没有invloced的asp.net服务器代码(在消息机制中).只有NodeJs.

题 :

这是正确的方法吗?(或者我错过了什么?)

fre*_*ish 64

这不仅是正确的方法,而且是唯一的方法.基本上每个连接都需要一个唯一的ID.否则你将无法识别它们,就像那样简单.

现在你将如何代表它,这是另一回事.使用idconnection属性创建一个对象是一个很好的方法(我肯定会这样做).您也可以id直接将其附加到连接对象.

还要记住,如果你想要用户之间的通信,那么你也必须发送目标用户的ID,即当用户A想要向用户B发送消息时,显然A必须知道B的ID.

  • @freakish:小心,这对于一个进程应用程序来说只是一个很好的解决方案.如果使用多个进程(或服务器)扩展应用程序,它们将不共享相同的内存 - 因此使用本地存储的对象的迭代将不起作用.最好直接迭代所有本地连接,将UUID存储在连接本身上.另外,对于缩放我会推荐Redis. (8认同)
  • @AsishAP,这是一个很长的讨论...我建议您首先阅读[这篇文章](https://hackernoon.com/scaling-websockets-9a31497af051)只是为了获得方向,而不是搜索其他问题, [这里有一篇值得一读](/sf/ask/329729431/)。 (2认同)

ma1*_*w28 32

这是一个简单的聊天服务器私人/直接消息传递.

package.json

{
  "name": "chat-server",
  "version": "0.0.1",
  "description": "WebSocket chat server",
  "dependencies": {
    "ws": "0.4.x"
  }
}
Run Code Online (Sandbox Code Playgroud)

server.js

var webSocketServer = new (require('ws')).Server({port: (process.env.PORT || 5000)}),
    webSockets = {} // userID: webSocket

// CONNECT /:userID
// wscat -c ws://localhost:5000/1
webSocketServer.on('connection', function (webSocket) {
  var userID = parseInt(webSocket.upgradeReq.url.substr(1), 10)
  webSockets[userID] = webSocket
  console.log('connected: ' + userID + ' in ' + Object.getOwnPropertyNames(webSockets))

  // Forward Message
  //
  // Receive               Example
  // [toUserID, text]      [2, "Hello, World!"]
  //
  // Send                  Example
  // [fromUserID, text]    [1, "Hello, World!"]
  webSocket.on('message', function(message) {
    console.log('received from ' + userID + ': ' + message)
    var messageArray = JSON.parse(message)
    var toUserWebSocket = webSockets[messageArray[0]]
    if (toUserWebSocket) {
      console.log('sent to ' + messageArray[0] + ': ' + JSON.stringify(messageArray))
      messageArray[0] = userID
      toUserWebSocket.send(JSON.stringify(messageArray))
    }
  })

  webSocket.on('close', function () {
    delete webSockets[userID]
    console.log('deleted: ' + userID)
  })
})
Run Code Online (Sandbox Code Playgroud)

说明

要测试它,请运行npm install安装ws.然后,要启动聊天服务器,请在一个"终端"选项卡中运行node server.js(或npm start).然后,在另一个终端选项卡中运行wscat -c ws://localhost:5000/1,其中1是连接用户的用户ID.然后,在第三终端选项卡,运行wscat -c ws://localhost:5000/2,然后从用户发送消息21输入["1", "Hello, World!"].

缺点

这个聊天服务器非常简单.

  • 坚持

    它不会将消息存储到数据库,例如PostgreSQL.因此,您要发送消息的用户必须连接到服务器才能接收消息.否则,消息将丢失.

  • 安全

    这是不安全的.

    • 如果我知道服务器的URL和Alice的用户ID,那么我可以冒充Alice,即以她的身份连接到服务器,允许我接收她的新传入消息并将消息从她发送给任何用户ID我也知道的用户.为了使其更安全,请在连接时修改服务器以接受访问令牌(而不是您的用户ID).然后,服务器可以从您的访问令牌中获取您的用户ID并对您进行身份验证.

    • 我不确定它是否支持WebSocket Secure(wss://)连接,因为我只测试了它localhost,而且我不确定如何安全连接localhost.


Dyl*_*ndy 8

对于使用ws版本 3 或更高版本的人。如果您想使用@ma11hew28提供的答案,只需按如下方式更改此块即可。

webSocketServer.on('connection', function (webSocket) {
  var userID = parseInt(webSocket.upgradeReq.url.substr(1), 10)
Run Code Online (Sandbox Code Playgroud)
webSocketServer.on('connection', function (webSocket, req) {
  var userID = parseInt(req.url.substr(1), 10)
Run Code Online (Sandbox Code Playgroud)

ws包已移至upgradeReq请求对象,您可以查看以下链接以获取更多详细信息。

参考:https : //github.com/websockets/ws/issues/1114