Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

node-websocket-server: possible to have multiple, separate "broadcasts" for a single node.js process?

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.

like image 400
S M Avatar asked Dec 15 '10 01:12

S M


People also ask

Can a WebSocket have multiple connections?

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.

How many WebSockets can a node server handle?

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).

How many WebSocket connections can a server hold?

By default, a single server can handle 65,536 socket connections just because it's the max number of TCP ports available.

Would WebSockets be able to handle 1000000 concurrent connections?

With at least 30 GiB RAM you can handle 1 million concurrent sockets.


2 Answers

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.

like image 122
Shripad Krishna Avatar answered Oct 05 '22 22:10

Shripad Krishna


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.

like image 24
Shawn Mclean Avatar answered Oct 05 '22 21:10

Shawn Mclean