使用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。 它看到的只是连接。
所以,我相信现在,我不应该只通过它们的连接来存储用户,而是需要存储一个对象 – 它将包含userId
和connection
对象。
这是我的想法:
-
当页面加载完成时(Dom准备就绪) – build立到NodeJs服务器的连接。
-
当NodeJs服务器接受连接时 – 生成一个唯一的string并将其发送到客户端浏览器。 将用户连接和唯一string存储在一个对象中。 例如
{UserID:"6" , value :{connectionObject}}
-
在客户端,当这个消息到达时 – 存储在一个隐藏的字段或cookie。 (用于将来对NodeJs服务器的请求)
当服务器想要发送消息给John时:
- 在字典中查找john的UserID并通过相应的连接发送消息。
请注意,这里没有任何asp.net服务器代码(在消息机制中)。 只有NodeJs。
题 :
这是正确的路吗? (或者我错过了什么?)
这不仅是正确的路,而且是唯一的途径。 基本上每个连接都需要一个唯一的ID。 否则,你将无法识别它们,就像这样简单。
现在你将如何performance这是另一回事。 使用id
和connection
属性来创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 }