admin管理员组文章数量:1431466
I want to make a notifications system based on events triggered by a user and gets delivered to another user ('X wrote on your wall). I understand the logic of broadcasting event, but if I broadcast, the message will be sent to everyone on the channel.
I am using Laravel 5 and I used Jeffrey Way's Nodejs, Redis, Socket.io tutorial. Very helpful.
For broadcasting and catching the messages,
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);
Client
<script> var socket = io('http://localhost:3000'); socket.on('globalNotificationChannel:WroteOnWall', function(data) { // (Notification Received) // console.log(data.message) }.bind(this)); } <script>
Triggering Action
$data = [ 'event' => 'WroteOnWall', 'data' => [ 'message' => $username + ' wrote on your wall.' ] ]; Redis::publish('globalNotificationChannel', json_encode($data));
Until here everything is clear however at this point I got lost. I have couple of questions.
First, how do I deliver the triggered event to a specific user's channel if everyone gets subscribed on the same channel.
Or is there a way of making unique channels? If so, how can I store the unique_channel_ids to prevent any bug?
And secondly, I have seen people are using cluster. Is it a good use for my case? Will it give me any benefits to me?
Note that on the Client side, I inserted it in master page as I need to run in every page, but now, I need to call 'connection' and 'listening' in every page. When re-run the connection scripts won't I end up with differing socketids?
Edit: I found this SO answer, and I believe it solves my problem, but I couldn't adapt it on redis instance.
I want to make a notifications system based on events triggered by a user and gets delivered to another user ('X wrote on your wall). I understand the logic of broadcasting event, but if I broadcast, the message will be sent to everyone on the channel.
I am using Laravel 5 and I used Jeffrey Way's Nodejs, Redis, Socket.io tutorial. Very helpful.
For broadcasting and catching the messages,
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);
Client
<script> var socket = io('http://localhost:3000'); socket.on('globalNotificationChannel:WroteOnWall', function(data) { // (Notification Received) // console.log(data.message) }.bind(this)); } <script>
Triggering Action
$data = [ 'event' => 'WroteOnWall', 'data' => [ 'message' => $username + ' wrote on your wall.' ] ]; Redis::publish('globalNotificationChannel', json_encode($data));
Until here everything is clear however at this point I got lost. I have couple of questions.
First, how do I deliver the triggered event to a specific user's channel if everyone gets subscribed on the same channel.
Or is there a way of making unique channels? If so, how can I store the unique_channel_ids to prevent any bug?
And secondly, I have seen people are using cluster. Is it a good use for my case? Will it give me any benefits to me?
Note that on the Client side, I inserted it in master page as I need to run in every page, but now, I need to call 'connection' and 'listening' in every page. When re-run the connection scripts won't I end up with differing socketids?
Edit: I found this SO answer, and I believe it solves my problem, but I couldn't adapt it on redis instance.
Share Improve this question edited May 23, 2017 at 12:09 CommunityBot 11 silver badge asked Oct 6, 2015 at 1:54 sentysenty 12.9k30 gold badges141 silver badges267 bronze badges 4- Here are two ways I've seen it done: 1. Keep reference to the user's sockets on the server. OR 2. Have the users join a unique room generated from their id and use that room to reach them. I prefer 2. – Dave Thomas Commented Oct 6, 2015 at 2:16
- If 2 is better, I'd go for 2. But, as far as I understand, there are 3 dimensions: channel - event - event data. What do you mean by rooms? Channels? Is there something I am missing? – senty Commented Oct 6, 2015 at 2:19
- Rooms as specified here: socket.io/docs/rooms-and-namespaces – Dave Thomas Commented Oct 6, 2015 at 2:26
-
So, it's just in the server side, I just use
io.connected[socketid].emit(channel + ':' + message.event, message.data);
instead ofio.emit(channel + ':' + message.event, message.data);
? – senty Commented Oct 6, 2015 at 2:35
1 Answer
Reset to default 7Alright here it is as per #2 in my ment above. Forgive me for not including Redis into the mix here.
Your server probably has some sort of authentication login endpoint. I'm going to use json web token in this example. You may use something else. But you will need a way identify your users in your socket connections. https://auth0./blog/2014/01/15/auth-with-socket-io/
A client authenticates in some way perhaps a RESTful API call and gets a json web token:
//Server
var jwt = require('jsonwebtoken');
var returnedToken = jwt.sign(user, app.get('superSecret'), {
expiresInMinutes: 1440 // expires in 24 hours
});
Then they connect to your socket.io server passing that token in the query as ?token="fasfsadfsaf"
//Client
var socket = io('http://localhost:3000', { query: 'token='+token });
On your sever you handle decoding the token into a user
//Server
//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);
});
The user can now be reached by broadcasting to that room
io.to('user_room_'+referenceToSameUserId).emit('Your message');
For your other questions:
Cluster will help you scale across multiple processes/servers. Redis helps with this as well. Add this when you got the basic frame down.
If your users are reconnecting at every page perhaps the pages should be loaded with ajax? You don't have to worry about different socket ids if you are identifying the users by some sort of authentication method rather than by the socket id.
Sorry if this answer isn't a plete answer, I'm new to this stuff too as well. But hopefully this is some direction that you can work with. Just helping some more since I started off in the ments.
本文标签: javascriptEvent Broadcasting to a Specific User (socketioredisnode)Stack Overflow
版权声明:本文标题:javascript - Event Broadcasting to a Specific User (socket.io, redis, node) - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744799430a2625774.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论