node.js socket 如何实现 接受 laravel 通知, 对单一用户发送数据

参照 realtime-laravel-app-with-socket-io 视频实现的

laravel 部分 给redis指定频道推送一条数据,

Route::get('redis', function () {
    $data = [
        'evnet' => 'test',
        'data'  => [
            'name' => [1, 2, 3, 4, 4, 5, 667, 123],
        ],
    ];
    \Redis::publish('test-channel', json_encode($data));
    return view('welcome');
});

node.js 部分, 订阅一个 redis 的频道, 利用 socket.io 推送给前端

var http = require('http').Server();
var io = require('socket.io')(http);
var Redis = require('ioredis');
var redis = new Redis();
// 订阅频道
redis.subscribe('test-channel');
redis.on('message', function (channel, messages) {
    messages = JSON.parse(messages);
    console.log(messages, channel);
    io.emit(channel, messages.data);
});
// web server
http.listen(3000, function () {
    console.log('server listen');
});

html 部分, socket 监听 频道, 获取 node 给到的数据

 var socket = io('192.168.88.20:3000');
    socket.on('test-channel', function (data) {
    console.log(data);
});

这样的每个打开的游览器都能够接受到数据,
可是实际中应该是根据 不同的用户去发送不同的数据, 我想过根据 UID 来实现, 但是现在 UID 是自增的, 如果我随便改下不就也能接受到别人的数据了吗,

这个判断应该在 laravel 完成还是 node 来完成呢?

JellyBool

你可以交给laravel来处理啊,后面不是说了laravel的broadcast事件么?基本上可以这样:

 public function broadcastOn()
    {
        return ['user.'.$this->user->id];
    }

或者你偷懒一点,可以在客户端用js判断是否是该用户id,是的话就显示消息就可以了

sodasix

@JellyBool

还是得考虑下安全问题吧, 全部都发送有点不好,

zonghua

我也想知道是怎么实现点对点用户推送的,我只知道http的session,其他mqtt什么的不知道怎么确定身份。

sodasix

我是这样实现的, php 发布消息到 redis 的时候, 增加一个字段, 如代码我是直接 md5了 用户登陆账号, 然后再 node.js 接受到 redis 信息的时候, 获取到 sendTo , 然后 socket 广播一条channel:’ + messages.sendTo 的广播, 再 HTML socket 监听相应的广播

php

 $md5Account = md5($event->member->user_account);
            $data = [
                'sendTo' => $md5Account,
                'data'   => [
                    'ToUser'     => $md5Account,
                    'status'     => $event->order->status,
                    'statusText' => $event->order->stateThat(),
                    'order'      => $event->order->order_id,
                ],
            ];
            // 发布到redis 对应频道
            \Redis::publish('orderStatusChange', json_encode($data));

node.js

// 订阅频道
redis.subscribe('orderStatusChange');
redis.on('message', function (channel, messages) {
    messages = JSON.parse(messages);
    io.emit(channel + ':' + messages.sendTo, messages.data);
});

html

var socketUserAccount = "{ md5($userinfo->user_account) }";
    var socket = io('domain:8081');
    socket.on('orderStatusChange:' + socketUserAccount, function (data) {
       
    });

@zonghua

xiqincai6

GoEasy也可以实现这个功能,自己感觉GoEasy要比Node.js简单易懂些GoEasy推送专注做web实时推送,服务稳定,中英文文档齐全,是个很不错的选择!官网:https://goeasy.io
如果你要对单一用户推送,那么直需要指定不同的channel再推送就好了

sodasix

@xiqincai6 - -自己能够解决的… 还是不依赖第三方吧

xiqincai6

@sodasix 单纯的推送功能从缩减开发成本的角度看,使用第三方是个不错的选择,而且不用担心有什么致命的bug出现,只为追求高效稳定。