Real-Time Notifications with Node.JS and Socket.IO

A lot of developers love things that are free and open-source, and would prefer to run a LAMP stack over WISA stack (Windows, IIS, Sql Server, Asp.Net)… but I’ll admit that when it comes to my day-job, I will pretty much always prefer the latter of the two. I do have my reasons for preferring the Microsoft platform and I am not trying to argue that one technology is better than the other. However, regardless of my preferred tech stack, sometimes you just need to select the platform that will provide the best solution for the problem. In the case of a real-time notification server/service, for me the ideal solution for this service would be to use Node.JS and Socket.IO running on a Linux OS…

Node.JS

Node.JS is a relatively new development platform that is based on chromium’s V8 JavaScript engine, and hence uses the JavaScript language. Node.JS uses an event-driven, non-blocking model (reducing the number of threads needed for our web server) and thus would be a good platform for our real-time notification server since a service like this would need to accomodate many persistent connections that each do little to no work.

Socket.IO

Socket.IO provides a simple framework for creating and managing persistent connections from a JS client (web browser or node.js app) and consists of two pieces: the server side component; and the client side component.

The Real-Time Notification Server

Here is an example of a very basic implementation of an RTN server. This might get you by in a personal project, or a site with relatively low traffic, but you would definitely want to implement clustering if you are thinking about doing something like this on a well utilized web site.

try
{
	var sio = require('socket.io');

	var io = sio.listen(8080).set('log level', 2);
	var pres = io.of("/notify").on('connection', function (socket) {

		// Clients need to send a "user" message to identify themselves...
		socket.once("user", function(userData)
		{
			try
			{
				// Make sure we have the data we need...
				if (userData == null || (userData.Id || null) == null) {
					return;
				}

				// Join the user to their own private channel so we can send them notifications...
				socket.join(userData.Id);
			} catch (e) { console.log(e); }
		 });

		// We can now "push" information to the user from any process that can connect to this service...
		socket.on("push", function(data)
		{
			try 
			{
				// Make sure we have the data we need...
				if (data == null || (data.Id || null) == null) {
					return;
				}
				console.log(data);

				// Let's clean up the data a little (we don't need to tell the user who they are)
				var channel = data.Id;
				delete data.Id;

				// Now we will braodcast the data only to the user's private channel...
				socket.broadcast.to(channel, data).emit("update", data)
			} catch (e) { console.log(e); }
		});
	});
} catch (e)
{
	console.log(e);
}

The Client

Here is a very simple Node.JS client script that connects to the server, announces itself, and just waits for notification data…

try
{
	var io = require('socket.io-client');

	var socket = io.connect('http://localhost:8080/notify');

	socket.on("connect", function() {
		console.log("connected");
		// Let the server know who is connected...
		socket.emit("user", { Id: 101 });
	});
	socket.on('update', function (data) {
		// Do something cool like update badges/status/etc...
		console.log(data);
	});
} catch (e) { console.log(e); }

Finally…

The last piece that is required is to actually push out a notification. Most implementations would have events generated or monitored by a seperate system, which could/would then send a “push” out through the Real-Time Notification System. This sample Node.JS script pushes out a notification for user 101, then a couple seconds later send an update to user 102…

try
{
	var io = require('socket.io-client');

	var socket = io.connect('http://localhost:8080/notify');

	socket.once("connect", function() {
		console.log("connected");

		setTimeout(function() {
			socket.emit("push", { Id: 101, Counts: { NewMessages: 3 } });
			setTimeout(function() {
				socket.emit("push", { Id: 102, Counts: { NewMessages: 5 } });
			}, 2000);
		}, 4000);

	});
} catch (e) { console.log(e); }

Check it Out!

The “user online” count on this site is now using a basic Real-Time notification system very similar to the one here to keep the online count up to date. Try browsing here in a new browser tab (or window) and watch the online count change!

Peter Femiani About Peter Femiani

Peter is currently a systems architect for a leading social networking company.

Speak Your Mind

*