I'd like to know if it's possible to broadcast on different websocket "connections" running from the same node-websocket-server app instance. Imagine a chatroom server with multiple rooms, only broadcasting messages to the participants specific to each room, on a single node.js server process. I've successfully implemented a one-chatroom-per-process solution, but I want to take it to the next level.
A server can open WebSocket connections with multiple clients—even multiple connections with the same client. It can then message one, some, or all of these clients. Practically, this means multiple people can connect to our chat app, and we can message some of them at a time.
The theoretical limit is 65k connections per IP address but the actual limit is often more like 20k, so we use multiple addresses to connect 20k to each (50 * 20k = 1 mil).
By default, a single server can handle 65,536 socket connections just because it's the max number of TCP ports available.
With at least 30 GiB RAM you can handle 1 million concurrent sockets.
You would probably like to try Push-it: http://github.com/aaronblohowiak/Push-It which is built on top of Socket.IO. Design adheres to the Bayeux Protocol.
However, if you need something that uses redis pubsub you can check http://github.com/shripadk/Socket.IO-PubSub
Specifically answering your question: You can maintain an array of all the clients connected to the websocket server. And probably just broadcast to a subset of those clients? The broadcast method does essentially that under the hood. node-websocket-server/Socket.IO maintains an array of all the clients connected and just loops through all of them "send"ing a message to each of the clients. Gist of the code:
// considering you storing all your clients in an array, should be doing this on connection: clients.push(client) // loop through that array to send to each client Client.prototype.broadcast = function(msg, except) { for(var i in clients) { if(clients[i].sessionId !== except) { clients[i].send({message: msg}); } } }
So if you want to relay messages only to specific channels, just maintain a list of all the channels subscribed by the client. Here is a simple example (to just get you started) :
clients.push(client); Client.prototype.subscribe = function(channel) { this.channel = channel; } Client.prototype.unsubscribe = function(channel) { this.channel = null; } Client.prototype.publish = function(channel, msg) { for(var i in clients) { if(clients[i].channel === channel) { clients[i].send({message: msg}); } } }
To make it even easier use EventEmitters. So in node-websocket-server/Socket.IO see where the messages are being received and parse the message to check the type (subscribe/unsubscribe/publish) and emit the event with the message depending on the type. Example:
Client.prototype._onMessage = function(message) { switch(message.type) { case 'subscribe': this.emit('subscribe', message.channel); case 'unsubscribe': this.emit('unsubscribe', message.channel); case 'publish': this.emit('publish', message.channel, message.data); default: } }
Listen to the events emitted in your app's on('connection') :
client.on('subscribe', function(channel) { // do some checks here if u like client.subscribe(channel); }); client.on('unsubscribe', function(channel) { client.unsubscribe(channel); }); client.on('publish', function(channel, message) { client.publish(channel, message); });
Hope this helps.
I'm not sure if rooms were a feature when the other answers were created, but in the documentation, they have a feature exactly what you are looking for. So go to that link and search for rooms
.
Here is an example from the site:
var io = require('socket.io').listen(80); io.sockets.on('connection', function (socket) { socket.join('justin bieber fans'); socket.broadcast.to('justin bieber fans').emit('new fan'); io.sockets.in('rammstein fans').emit('new non-fan'); });
Based on the other answers, it was more focused on scaling, I would love some insight if the built in version scales well as the proposed answers.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With