首页 文章

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

提问于
浏览
58

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

The Used code : (简要)

// 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;
    ...

请注意 :

  • 我没有任何用户参考,只有一个连接 .

  • 所有用户连接都存储在 array 中 .

Goal :假设NodeJs服务器想要向 specific 客户端(John)发送消息 .

这是一个问题:

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

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

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

这是我的想法:


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

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

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


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

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

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

Question :

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

3 回答

  • 29

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

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

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

  • 1

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

    package.json

    {
      "name": "chat-server",
      "version": "0.0.1",
      "description": "WebSocket chat server",
      "dependencies": {
        "ws": "0.4.x"
      }
    }
    

    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)
      })
    })
    

    说明

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

    缺点

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

    • 持久性

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

    • 安全

    这是不安全的 .

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

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

  • 59

    我想分享一下我的所作所为 . 希望它不浪费你的时间 .

    我创建了数据库表保存字段ID,IP,用户名,登录时间和注销时间 . 当用户登录logintime时,将显示unixtimestamp unix . 当在websocket数据库中启动连接时检查最大的登录时间 . 它将是用户登录的 .

    并且当用户注销时,它将存储当前的注销时间 . 用户将成为离开应用程序的人 .

    每当有新消息时,都会比较Websocket ID和IP,并显示相关的用户名 . 以下是示例代码......

    // when a client connects
    function wsOnOpen($clientID) {
          global $Server;
          $ip = long2ip( $Server->wsClients[$clientID][6] );
    
          require_once('config.php');
          require_once CLASSES . 'class.db.php';
          require_once CLASSES . 'class.log.php';
    
          $db = new database();
          $loga = new log($db);
    
          //Getting the last login person time and username
          $conditions = "WHERE which = 'login' ORDER BY id DESC LIMIT 0, 1";
          $logs = $loga->get_logs($conditions);
          foreach($logs as $rows) {
    
                  $destination = $rows["user"];
                  $idh = md5("$rows[user]".md5($rows["time"]));
    
                  if ( $clientID > $rows["what"]) {
                          $conditions = "ip = '$ip', clientID = '$clientID'  
    
                          WHERE logintime = '$rows[time]'";
                          $loga->update_log($conditions);
                 }
          }
          ...//rest of the things
    }
    

相关问题