向特定用户广播事件(socket.io、redis、node)
Event Broadcasting to a Specific User (socket.io, redis, node)
我想制作一个通知系统,它基于一个用户触发的事件并传递给另一个用户('X 写在你的墙上)。我明白广播事件的逻辑,但是如果我广播,消息将发送给频道上的每个人。
我正在使用 Laravel 5 并且我使用了 Jeffrey Way 的 Nodejs, Redis, Socket.io tutorial。很有帮助。
用于广播和捕获消息,
Server.js
var server = require('http').Server();
var io = require('socket.io')(server);
var Redis = require('ioredis');
var redis = new Redis();
redis.subscribe('globalNotificationChannel');
redis.on('message', function(channel, message) {
message = JSON.parse(message);
io.emit(channel + ':' + message.event, message.data);
});
server.listen(3000);
客户
<script>
var socket = io('http://localhost:3000');
socket.on('globalNotificationChannel:WroteOnWall', function(data) {
// (Notification Received)
// console.log(data.message)
}.bind(this));
}
<script>
触发操作
$data = [
'event' => 'WroteOnWall',
'data' => [
'message' => $username + ' wrote on your wall.'
]
];
Redis::publish('globalNotificationChannel', json_encode($data));
到这里为止一切都很清楚,但是此时我迷路了。我有几个问题。
首先,如果每个人都订阅了同一频道,我如何将触发的事件传送到特定用户的频道。
或者有没有办法制作独特的频道?如果是这样,我如何存储 unique_channel_ids 以防止任何错误?
其次,我看到有人在使用集群。它对我的情况有用吗?它会给我带来什么好处吗?
请注意,在客户端,我将其插入母版页中,因为我需要在每个页面中 运行,但现在,我需要调用 'connection' 和 'listening' 在每一页。当重新 运行 连接脚本时,我不会以不同的 socketids 结束吗?
编辑:我发现 this SO answer,我相信它解决了我的问题,但我无法在 redis 实例上调整它。
好的,这是我上面评论中的 #2。请原谅我没有将 Redis 纳入其中。
您的服务器可能有某种身份验证登录端点。我将在此示例中使用 json 网络令牌。你可以用别的东西。但是您需要一种方法来识别套接字连接中的用户。
https://auth0.com/blog/2014/01/15/auth-with-socket-io/
客户端可能以某种方式验证 RESTful API 调用并获取 json 网络令牌:
//服务器
var jwt = require('jsonwebtoken');
var returnedToken = jwt.sign(user, app.get('superSecret'), {
expiresInMinutes: 1440 // expires in 24 hours
});
然后他们连接到您的 socket.io 服务器,在查询中将该令牌作为 ?token="fasfsadfsaf"
传递
//客户端
var socket = io('http://localhost:3000', { query: 'token='+token });
在您的服务器上,您负责将令牌解码为用户
//服务器
//This adds the jwt session token to handshake when connecting to the socket
var socketioJwt = require('socketio-jwt');
io.use(socketioJwt.authorize({
secret:'superSecret',
handshake:true
}));
//When a user connects throw them in their own unique room
io.on('connection', function (socket) {
//This will get the encoded user object in the JWT token
var user = socket.decoded_token;
//This puts them into their unique room
socket.join('user_room_'+user._id);
});
现在可以通过向该房间广播来联系用户
io.to('user_room_'+referenceToSameUserId).emit('Your message');
关于您的其他问题:
集群将帮助您扩展多个 processes/servers。 Redis 对此也有帮助。当你把基本框架弄下来的时候加上这个。
如果您的用户在每个页面都重新连接,也许页面应该加载 ajax?如果您通过某种身份验证方法而不是套接字 ID 来识别用户,则不必担心不同的套接字 ID。
抱歉,如果这个答案不是一个完整的答案,我也是这方面的新手。但希望这是您可以合作的方向。自从我开始在评论中提供更多帮助。
我想制作一个通知系统,它基于一个用户触发的事件并传递给另一个用户('X 写在你的墙上)。我明白广播事件的逻辑,但是如果我广播,消息将发送给频道上的每个人。
我正在使用 Laravel 5 并且我使用了 Jeffrey Way 的 Nodejs, Redis, Socket.io tutorial。很有帮助。
用于广播和捕获消息,
Server.js
var server = require('http').Server(); var io = require('socket.io')(server); var Redis = require('ioredis'); var redis = new Redis(); redis.subscribe('globalNotificationChannel'); redis.on('message', function(channel, message) { message = JSON.parse(message); io.emit(channel + ':' + message.event, message.data); }); server.listen(3000);
客户
<script> var socket = io('http://localhost:3000'); socket.on('globalNotificationChannel:WroteOnWall', function(data) { // (Notification Received) // console.log(data.message) }.bind(this)); } <script>
触发操作
$data = [ 'event' => 'WroteOnWall', 'data' => [ 'message' => $username + ' wrote on your wall.' ] ]; Redis::publish('globalNotificationChannel', json_encode($data));
到这里为止一切都很清楚,但是此时我迷路了。我有几个问题。
首先,如果每个人都订阅了同一频道,我如何将触发的事件传送到特定用户的频道。
或者有没有办法制作独特的频道?如果是这样,我如何存储 unique_channel_ids 以防止任何错误?
其次,我看到有人在使用集群。它对我的情况有用吗?它会给我带来什么好处吗?
请注意,在客户端,我将其插入母版页中,因为我需要在每个页面中 运行,但现在,我需要调用 'connection' 和 'listening' 在每一页。当重新 运行 连接脚本时,我不会以不同的 socketids 结束吗?
编辑:我发现 this SO answer,我相信它解决了我的问题,但我无法在 redis 实例上调整它。
好的,这是我上面评论中的 #2。请原谅我没有将 Redis 纳入其中。
您的服务器可能有某种身份验证登录端点。我将在此示例中使用 json 网络令牌。你可以用别的东西。但是您需要一种方法来识别套接字连接中的用户。 https://auth0.com/blog/2014/01/15/auth-with-socket-io/
客户端可能以某种方式验证 RESTful API 调用并获取 json 网络令牌:
//服务器
var jwt = require('jsonwebtoken');
var returnedToken = jwt.sign(user, app.get('superSecret'), {
expiresInMinutes: 1440 // expires in 24 hours
});
然后他们连接到您的 socket.io 服务器,在查询中将该令牌作为 ?token="fasfsadfsaf"
传递//客户端
var socket = io('http://localhost:3000', { query: 'token='+token });
在您的服务器上,您负责将令牌解码为用户
//服务器
//This adds the jwt session token to handshake when connecting to the socket
var socketioJwt = require('socketio-jwt');
io.use(socketioJwt.authorize({
secret:'superSecret',
handshake:true
}));
//When a user connects throw them in their own unique room
io.on('connection', function (socket) {
//This will get the encoded user object in the JWT token
var user = socket.decoded_token;
//This puts them into their unique room
socket.join('user_room_'+user._id);
});
现在可以通过向该房间广播来联系用户
io.to('user_room_'+referenceToSameUserId).emit('Your message');
关于您的其他问题:
集群将帮助您扩展多个 processes/servers。 Redis 对此也有帮助。当你把基本框架弄下来的时候加上这个。
如果您的用户在每个页面都重新连接,也许页面应该加载 ajax?如果您通过某种身份验证方法而不是套接字 ID 来识别用户,则不必担心不同的套接字 ID。
抱歉,如果这个答案不是一个完整的答案,我也是这方面的新手。但希望这是您可以合作的方向。自从我开始在评论中提供更多帮助。