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

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

使用的代码:( 简短)

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

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

这里是一个问题:

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

    NodeJs服务器甚至不知道John。 它看到的只是连接。

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

这是我的想法:


  • 当页面加载完成时(Dom准备就绪) – build立到NodeJs服务器的连接。

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

  • 在客户端,当这个消息到达时 – 存储在一个隐藏的字段或cookie。 (用于将来对NodeJs服务器的请求)


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

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

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

题 :

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

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

现在你将如何performance这是另一回事。 使用idconnection属性来创build对象是一个很好的方法来做到这一点(我一定会去做的)。 你也可以直接将id附加到连接对象。

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

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

package.json

 { "name": "chat-server", "version": "0.0.1", "description": "WebSocket chat server", "author": "Matt Di Pasquale (mattdipasquale.com)", "dependencies": { "ws": "0.4.x" }, "engines": { "node": "0.10.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) }) }) 

说明

要testing它,运行npm install来安装ws 。 然后,要启动聊天服务器,请在一个“terminal”选项卡中运行node server.js (或npm start )。 然后,在另一个“terminal”选项卡中,运行wscat -c ws://localhost:5000/1 ,其中1是连接用户的用户标识。 然后,在第三个Terminal选项卡中,运行wscat -c ws://localhost:5000/2 ,然后从用户2发送消息到1 ,input["1", "Hello, World!"]

缺点

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

  • 坚持

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

  • 安全

    这是不安全的。

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

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

我想分享我所做的。 希望它不会浪费你的时间。

我创build了数据库表,包含字段ID,IP,用户名,login时间和注销时间。 当用户login时将login时间unixtimestamp unix。 当websocket数据库连接开始时,检查最大的login时间。 它会来用户login。

而当用户注销它将存储正确的注销时间。 用户将成为谁离开了应用程序。

每当有新消息时,比较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 }