javascript - 向特定用户广播事件(socket.io、redis、node)

标签 javascript node.js sockets redis socket.io

我想制作一个通知系统,该系统基于用户触发的事件并传递给另一个用户('X wrote on your wall)。我理解广播事件的逻辑,但是如果我广播,消息将发送给 channel 上的每个人。

我正在使用 Laravel 5,我使用了 Jeffrey Way 的 Nodejs, Redis, Socket.io tutorial .很有帮助。

用于广播和捕获消息,

  • 服务器.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>
      
    • 触发 Action

      $data = [
        'event' => 'WroteOnWall',
        'data' => [
            'message' => $username + ' wrote on your wall.'
        ]
      ];
      
      Redis::publish('globalNotificationChannel', json_encode($data));
      

到这里一切都很清楚,但是此时我迷路了。我有几个问题。

  • 首先,如果每个人都订阅了同一 channel ,我该如何将触发事件传送到特定用户的 channel 。

  • 或者有没有办法制作独特的 channel ?如果是这样,我该如何存储 unique_channel_id 以防止出现任何错误?

  • 其次,我看到有人在使用集群。它对我的情况有用吗?它会给我带来什么好处吗?

  • 请注意,在客户端,我将它插入母版页中,因为我需要在每个页面中运行,但现在,我需要在每个页面中调用“连接”和“监听”。重新运行连接脚本时,我不会得到不同的 socketid 吗?

编辑:我找到了 this SO answer ,我相信它解决了我的问题,但我无法在 Redis 实例上调整它。

最佳答案

好的,这是我上面评论中的#2。请原谅我没有将 Redis 包括在内。

您的服务器可能有某种身份验证登录端点。在此示例中,我将使用 json 网络 token 。你可以用别的东西。但是您需要一种方法来识别套接字连接中的用户。 https://auth0.com/blog/2014/01/15/auth-with-socket-io/

客户端以某种方式验证 RESTful API 调用并获取 json 网络 token :

//服务器

var jwt = require('jsonwebtoken');
var returnedToken = jwt.sign(user, app.get('superSecret'), {
            expiresInMinutes: 1440 // expires in 24 hours
        });

然后他们连接到您的 socket.io 服务器,在查询中将该 token 作为 ?token="fasfsadfsaf"

//客户端

var socket = io('http://localhost:3000', { query: 'token='+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');

对于您的其他问题:

  • 集群将帮助您跨多个进程/服务器进行扩展。 Redis 对此也有帮助。当你放下基本框架时添加它。

  • 如果您的用户在每个页面都重新连接,也许页面应该使用 ajax 加载?如果您通过某种身份验证方法而不是套接字 ID 来识别用户,则不必担心不同的套接字 ID。

很抱歉,如果这个答案不是一个完整的答案,我也是这个东西的新手。但希望这是您可以合作的方向。自从我开始发表评论以来,只是帮助了更多人。

关于javascript - 向特定用户广播事件(socket.io、redis、node),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32960515/

相关文章:

java - 从套接字服务器发送 2 个图像

java - 通过 TCP 发送转换为字节数组的 XML,然后将响应转换回可读的 XML 的最佳方法是什么?

javascript - 如何从虚拟专用服务器检索文本文件?

javascript - RefineSlide 未显示在网站上

javascript - 以编程方式发送键盘事件不会将它们分派(dispatch)到输入中

javascript - Node.js 无法履行 promise (Promise { <pending> })

mysql - 表情符号未插入数据库 Node js mysql

javascript - VueJS如何更新选择数据

javascript - 如何验证用户输入?

linux - Amazon AWS EC2 Linux 上的 Node-gyp Connect-mongo