//Server setting....
//Store using Redis ..
this is the part of the code, now i have to send the stored data to other clients connected,the case is 'n' no.of application with 'n' no.of clients, so i have to create channels here dynamically. am asking u to help me by giving ideas for creating dynamic channel name for pub/sub.
This is not something Redis handles. You'll need to protect access to Redis pub/sub through an application layer. If you want to allow people to connect directly to Redis and still protect channels per user, I believe you're out of luck.
Related
I have searched long and far. I am typically familiar with the LAMP stack so apologies - I am learning Node as I'm trying to build a chat feature - similar to how Intercom/drift would work.
I have been led to believe that Socket.io is a good way to go about this, and I am having a little bit of trouble. The basic overview is something like this:
Users can use my service to have a live chat feature enabled on their websites (they each have a unique API key)
They can add the chat to any number of web pages/domains (via a script tag)
The chat should be private between any single end user of the website, and the admin of the script tag (owner of the API key used to include the script on the page)
I'm having trouble with this.
Should I create dynamic namespaces for each URL, or is it a room?
Lets say I create a dynamic room on the client side that is unique such as is used in https://stackoverflow.com/a/19150254/1173155
// client side code
var dynamicRoomName = API_KEY + "_" + fullURL + "_" + expressSessionId;
var socket = io.connect();
socket.emit('create room', dynamicRoomName);
// server side code
io.sockets.on('connection', function(socket) {
socket.on('create room', function(room) {
socket.join(room);
});
});
The only person who should be able to see this chat other than the end user is the admin of that API Key, which I'm not sure how to implement.
I realise I will likely need a DB of some sort to keep track of the chats/rooms ect. Is there any good resource on how to learn how to implement this kind of thing?
Help is much appreciated!
Just going to expand a small bit on this, perhaps for my own good while working on the problem.
There can be many admins (unique APIs)
Admins are responsible for only their own chats - they cannot see any chats that do not belong to their API key
Many users can chat with one admin (in private)
All chat is 1 to 1
The end user and the admin user will thus use different clients
Admin can be in numerous chats to individual users
Users would typically be in one chat to one admin
Admins can't create chats (only receive incoming) - but of course can reply
I don't think you want to use a namespace because then your server would have to be pre-listening on the server to every possible namespace in order to hear a connection to it. That seems impractical and inefficient. There are a number of different possible schemes. Here's one I think is fairly simple to implement.
You create one namespace for this admin chat.
Your server listens to that namespace and accepts incoming connections to it.
The client connects to that namespace when they want the chat with the admin.
The client then sends an initiateChat message with the API_KEY as data.
The server is coded to not accept any other messages until initiateChat has been received with a valid API_KEY
When the server receives the initiateChat message, it looks up the API_KEY in your database and if it finds it in the database and that user is currently online, it starts a chat session with them. If they are not currently available, it sends a message back to the client indicating they are not currently online.
Now the socket is open for chat related messages.
You can use a dynamically created room name to keep track of the two end points if you want and join both sockets to that room.
If the admin user can be involved in multiple chats with the same socket, then you will have to make sure the chat messages it sends are labeled with which chat they belong to so you know which room name to send the message to on your server.
I have an express server setup that is handling all of my routing and session stuff. I want the system to work so that when a user is logged in they are able to connect to a "hub" like entity that is uniquely based on the location of the "hub". I thought about working it like each of the "hubs" is a collection in a database, but the way it works is that a user connects to the "hub" and then disconnects from it when they are done but can connect to different "hubs" based on a location. How should I go about creating a unique group of "hub" like things that all act as objects with storable data?
Instead of connecting to a "hub", why not just present them with different information from a database based on their location. The user will never really connect to anything other than your single backend. Unless, ofcourse, you set up different servers all over the world (known as a CDN, and probably a bit too much effort).
If you're using express, you could use something like mongodb for data storage.
With mongodb you get the mongoose npm package. With that, you can create Schemas. You could have different Schemas as "hubs" and load the correct ones based on location data. That would let the user see different information for different locations.
I am trying to implement client to client messaging in my app, using socket.io, and node.js and Android.
I searched a little, and found a lot of tutorials, explaining how to deal with targetting specific client when sending messages through socket.io socket.
Send message to specific client with socket.io and node.js
The solution is almost always the same : Creating a hashmap object, linking user info such as its username, email address (or anything unique allowing to identify it), with its socketid.
Then calling io.clients[sessionID].send()
Now I have two questions :
This would work if only one instance of the app is running, but imagine if my app is divided in multiple instances (for large app).
What if a client A, connected to instance X, wants to send message to user B, connected to instance Z. If, as seen in the example, socketids are stored directly in a simple object existing in the script, some sockets wont know about others users existing in an other instance.
If I am totally wrong (and I might), is this a good practice to store all user's socketids in a single variable ? If yes, would it still be okay with a 50000+ users enviromnment ? If no, should I find another solution like storing user's socketids in database ?
You could use a redis instance, shared between all your app instances. And you get 2 birds with one stone.
The redis would store all your socket ids in a centralized place.
I am building a multiplayer turn based game, the communication between clients and server is established with Pusher. I can send events to all clients using game channels. The problem is how do I send an event to a single client? Pusher has no documentation for it, only seemingly solution is to use authenticated channels. Is it viable to authenticate a dedicated channel for every client sending events to a single client, or is there a better solution?
You touched on the best solution in your answer. You should be able to quite easily programmatically setup channels for each individual user and then just broadcast messages to them over those channels.
e.g. (this is a Ruby example but it should be clear what's happening)
user = SOME_USER_OBJECT
Pusher.trigger("card-data-#{user.id}", 'card-update', {data: {card_id: 1, status: 'used'})
or something like that. Obviously you'd then need to make sure that on the client side that the users are subscribing to the correct channels.
Obviously if you need the channels to be secure then, as you said, you can use authenticated channels - probably using private channels makes sense in your case.
If you have any more questions then you can reply here again and I'll take a look, or you can email support at support#pusher.com.
Instead of creating an individual channel you can subscribe to an individual event for each client.
PubNub Stream Filter
If you are using PubNub, you can either create a unique channel for each user and just publish the proper message to each of the channels or you can create a common channel for all of the users and use the Stream Filter feature so that each client only gets messages they want on that channel. This filtering is performed on the server side so the end user doesn't get unwanted messages that have to be ignored.
This is the simple high level steps for using Stream Filters
When you init PubNub on the client side, create a filter using the meta parameter
When you publish messages, add key/values to the meta parameter that will be used to filter messages on the PubNub Network before sending them to the subscribers (based on each individual subscriber's filter).
For full Stream Filter docs per SDK (that you mentioned via tags):
PubNub JavaScript SDK Stream Filter
PubNub Node SDK Stream Filter
PubNub Ruby SDK Stream Filter
You could also use PubNub BLOCKS to route each message to the appropriate user channel (or however you map your channels to end users) the on before publish event handler. I won't go into the details of this since it is slightly more involved but feel free to ask for additional insights as necessary. To get started, you can review the full BLOCKS docs.
Been researching heaps and making no progress :(
Trying to set up a small web app using VB in VS 2013.
I have added all the SignalR resources to my project.
Each logged in client has a UserID in my database.
I want to invoke a SignalR message to certain UserID's from server-side code, not client-side. Firstly, is this possible? (it was possible using ReverseAJAX, but I have chosen not to use that)
If it is possible, how do I go about setting up the SignalR Hub to allow me to send a message using a UserID? I don't need help with the SQL, I can do that my self.
Also, what javascript do I need to persist the request? I'm guessing I will need the UserID somewhere in this piece of code.
Thanks heaps.
This is very possible. If you look here
http://www.asp.net/signalr/overview/signalr-20/hubs-api/hubs-api-guide-server#callfromoutsidehub
you will find a section on "Single User Groups". This is the mechanism available in version 2 to send a message to a single User Id. Essentially when a Connection is established you add the User Id to a "group" which can be accessed by Group Name (syn. User Id) without having to worry about persisting the relationship of a connection id to a user id yourself. The only limitation would be if more than 1 connection is established by the same user, all devices with that user would be in the same group and would therefore receive any messages sent to it...
There is also another section on how to retain the instance of your SignalR context on the web server to make calls out to clients (How to call client methods and manage groups from outside the Hub class)
I did read something about the SignalR team creating User Id methods but I have used the above approach with fair success and haven't looked much further into that.
Hope this helps
As #Pepto mentioned, here it is described how you can get a reference to your hub, and then use it in your server code.
An easy way to invoke a client-side function for a specific user, would be to use Clients.User("Username") in your hub.
Intellisense will tell you that User() wants an ID as a parameter, but you should pass the username of the user, whose function you want to invoke, not his ID.