草庐IT

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

coder 2023-07-18 原文

我想制作一个通知系统,该系统基于用户触发的事件并传递给另一个用户('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/

有关javascript - 向特定用户广播事件(socket.io、redis、node)的更多相关文章

  1. ruby-openid:执行发现时未设置@socket - 2

    我在使用omniauth/openid时遇到了一些麻烦。在尝试进行身份验证时,我在日志中发现了这一点:OpenID::FetchingError:Errorfetchinghttps://www.google.com/accounts/o8/.well-known/host-meta?hd=profiles.google.com%2Fmy_username:undefinedmethod`io'fornil:NilClass重要的是undefinedmethodio'fornil:NilClass来自openid/fetchers.rb,在下面的代码片段中:moduleNetclass

  2. ruby-on-rails - 使用 rails 4 设计而不更新用户 - 2

    我将应用程序升级到Rails4,一切正常。我可以登录并转到我的编辑页面。也更新了观点。使用标准View时,用户会更新。但是当我添加例如字段:name时,它​​不会在表单中更新。使用devise3.1.1和gem'protected_attributes'我需要在设备或数据库上运行某种更新命令吗?我也搜索过这个地方,找到了许多不同的解决方案,但没有一个会更新我的用户字段。我没有添加任何自定义字段。 最佳答案 如果您想允许额外的参数,您可以在ApplicationController中使用beforefilter,因为Rails4将参数

  3. ruby - 如何验证 IO.copy_stream 是否成功 - 2

    这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下

  4. Ruby 文件 IO 定界符? - 2

    我正在尝试解析一个文本文件,该文件每行包含可变数量的单词和数字,如下所示:foo4.500bar3.001.33foobar如何读取由空格而不是换行符分隔的文件?有什么方法可以设置File("file.txt").foreach方法以使用空格而不是换行符作为分隔符? 最佳答案 接受的答案将slurp文件,这可能是大文本文件的问题。更好的解决方案是IO.foreach.它是惯用的,将按字符流式传输文件:File.foreach(filename,""){|string|putsstring}包含“thisisanexample”结果的

  5. ruby-on-rails - 简单的 Ruby on Rails 问题——如何将评论附加到用户和文章? - 2

    我意识到这可能是一个非常基本的问题,但我现在已经花了几天时间回过头来解决这个问题,但出于某种原因,Google就是没有帮助我。(我认为部分问题在于我是一个初学者,我不知道该问什么......)我也看过O'Reilly的RubyCookbook和RailsAPI,但我仍然停留在这个问题上.我找到了一些关于多态关系的信息,但它似乎不是我需要的(尽管如果我错了请告诉我)。我正在尝试调整MichaelHartl'stutorial创建一个包含用户、文章和评论的博客应用程序(不使用脚手架)。我希望评论既属于用户又属于文章。我的主要问题是:我不知道如何将当前文章的ID放入评论Controller。

  6. ruby - RVM "ERROR: Unable to checkout branch ."单用户 - 2

    我在新的Debian6VirtualBoxVM上安装RVM时遇到问题。我已经安装了所有需要的包并使用下载了安装脚本(curl-shttps://rvm.beginrescueend.com/install/rvm)>rvm,但以单个用户身份运行时bashrvm我收到以下错误消息:ERROR:Unabletocheckoutbranch.安装在这里停止,并且(据我所知)没有安装RVM的任何文件。如果我以root身份运行脚本(对于多用户安装),我会收到另一条消息:Successfullycheckedoutbranch''安装程序继续并指示成功,但未添加.rvm目录,甚至在修改我的.bas

  7. ruby-on-rails - 事件管理员日期过滤器日期格式自定义 - 2

    是否有简单的方法来更改默认ISO格式(yyyy-mm-dd)的ActiveAdmin日期过滤器显示格式? 最佳答案 您可以像这样为日期选择器提供额外的选项,而不是覆盖js:=f.input:my_date,as::datepicker,datepicker_options:{dateFormat:"mm/dd/yy"} 关于ruby-on-rails-事件管理员日期过滤器日期格式自定义,我们在StackOverflow上找到一个类似的问题: https://s

  8. Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting - 2

    1.错误信息:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:requestcanceledwhilewaitingforconnection(Client.Timeoutexceededwhileawaitingheaders)或者:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:TLShandshaketimeout2.报错原因:docker使用的镜像网址默认为国外,下载容易超时,需要修改成国内镜像地址(首先阿里

  9. Ruby - 如何在读取文件时跳过/忽略特定行? - 2

    在读取/解析文件(使用Ruby)时忽略某些行的最佳方法是什么?我正在尝试仅解析Cucumber.feature文件中的场景,并希望跳过不以Scenario/Given/When/Then/And/But开头的行。下面的代码有效,但它很荒谬,所以我正在寻找一个聪明的解决方案:)File.open(file).each_linedo|line|line.chomp!nextifline.empty?nextifline.include?"#"nextifline.include?"Feature"nextifline.include?"Inorder"nextifline.include?

  10. ruby-on-rails - 事件记录 : Select max of limit - 2

    我正在尝试将以下SQL查询转换为ActiveRecord,它正在融化我的大脑。deletefromtablewhereid有什么想法吗?我想做的是限制表中的行数。所以,我想删除少于最近10个条目的所有内容。编辑:通过结合以下几个答案找到了解决方案。Temperature.where('id这给我留下了最新的10个条目。 最佳答案 从您的SQL来看,您似乎想要从表中删除前10条记录。我相信到目前为止的大多数答案都会如此。这里有两个额外的选择:基于MurifoX的版本:Table.where(:id=>Table.order(:id).

随机推荐