RSS

Basic Node.js and Backbone.js application IV. Socket.io and Redis support

21 Abr

In this post we are going to add a key-value store called Redis and Socket.io (a Websocket implementation  to Node.js). Although Redis is often known as a NoSQL database, the fact is that we cannot include it as one. The same concept can apply to Socket.io. Commonly, it is mistaken with Websocket, Socket.io is an Websocket API that gives us some extra features over it.

Adding Socket.io to our project

We are going to use our current Backbone.js project (if you want to read about it, click to these links, Basic Node.js and Backbone.js application IBasic Node.js and Backbone.js application II and Basic Node.js and Backbone.js application III). Adding Socket.io to our projects is quite easy. As we saw with other modules we need to import into our application. In our case we add the following line into our file:

  sio = require("socket.io");
After that we have to make listen our Node.js application so that we can listen to every connection that comes from our clients. We can implement some methods to handle with the data and reply to their clients. We have several methods within the Socket.io API. In our case we are going to focus on socket.emit, io.sockets.emit and socket.broadcast.emit. This is our code:
var user = 0;
io.sockets.on('connection', function (socket) {
  user = user + 1;
  socket.user = user;
  socket.emit('user', user);
io.sockets.emit('nusers', user);

  socket.on('disconnect', function () {
    io.sockets.emit('nusers', user);
  });
});
We are going to complement this code with some Redis stuff, but it is enough to start with by now. First we will listen from every connection that comes to our Node.js server. To do that we use the io.socket.on method and we are going to bind it to the connection event. We will add a callback where we are going to implement our logic. For example, when a new client sends a new request to our server, it handles as follows:
  • It replies with the socket.emit method to the client.
  • It replies to every socket with the user value using the io.sockets.emit. We could use the socket.broadcast.emit method but this method only replies to the ones different of the current socket.

Obviously, we need to add some code to the client side in other to handle the replies from the server-side. Let’s  take a look at it:

!!! 5
html
 head
 script(src='https://ajax.googleapis.com/ajax//jquery/1.7.1/jquery.min.js')
 script(src='http://ajax.cdnjs.com/ajax/libs/json2/20110223/json2.js')
 script(src='http://documentcloud.github.com/underscore/underscore.js')
 script(src='http://documentcloud.github.com/backbone/backbone.js')
 script(src='/socket.io/socket.io.js')
 script
 // socket.io specific code
 var socket = io.connect();

socket.on('connect', function () {
 console.log('connected to the server ...');
 });

socket.on('user', function (msg) {
 $('#user').html('User ' + msg);
 });
 socket.on('nusers', function (nusers) {
 $('#nusers').html('Number of users: ' + nusers);
 });
 title My example page
 body
 #nusers
 #user
 block content
 #container!= body

It’s pretty simple, the only thing you need is to create a socket within you html code and listen to events from the server side. In our case we’ve seen that the server emits user and nuser events and some value. The only thing we are going to do is getting the value that has been sent from the server and show it in our client.

Adding Redis to our project.

We are going to improve our very little use the Socket.io giving some more functionality using Redis. What we are going to do is as follows:

  • From every client connection, server-side is going to send the user to the client. Besides that we are going to update every previous client connection to let it know how many clients that are connected to the server there are.
  • Besides that we are going to save every client id (just a number) into a set in our Redis store. We get every client/member from this set and broadcast to every client so that we can update every client with the new information.
  • If one client is disconnected from our server, the server gets its id and removes it from the Redis set. Server has to update every client with that information.

To do that, we add some more code to our Node.js server.

var user = 0;
io.sockets.on('connection', function (socket) {
  user = user + 1;
  socket.user = user;
  socket.emit('user', user);
  redis.sadd('users', user);
  redis.multi().smembers('users').exec(function (err, replies) {
    io.sockets.emit('nusers', replies[0].length, replies[0].toString());
  });
  socket.on('disconnect', function () {
    redis.srem('users',socket.user);
    redis.multi().smembers('users').exec(function (err, replies) {
      io.sockets.emit('nusers', replies[0].length, replies[0].toString());
    });
  });
});

Redis has a great API that give us the power to deal with all the data we store on it. You can take a look there if you need some more method. The above code is really simple anyway.

Before looking at the code we also need to notice that a Redis client is required. To create it we add this code:

  var red = require("redis");
  var redis = red.createClient();

You are going to need a Redis server in your localhost as well. Take a look at the official documentation. I also like this page.

On every connection:

  • We add the user to our Redis‘ users set. To do that we use the redis.add method
  • Get all the members from that store and update all client with that information. The method we have to execute is a little more complicated. We need to chain the multi method with smembers and exec. All you have to know is that smembers retrieves all the values within the set we pass as an argument. We also notice that the io.socket.emit has been modified with a third parameter where the list of users are indicated. We should modify our client code to get that information.
  • When a client is disconnected we are going to delete from the set store and update the information to every other client.

Testing our application.

All we are going to do is deploy our server and connect one client to it (a web browser instance). Then we will see how our client has received an ID from the server.

In this moment, there are just one client connected to the server. Let’s see what happens when a new client connects to the server.

The first client is also aware of the second client because of Socket.io.

Now we are going to open a third client and disconnect the second one. The following caption shows how the first client looks like after all.

What has happened is that the second client has sent a disconnect event to the server and this one has communicated to the other alive client the current situation.

Deploying to Heroku.

This application has been uploaded to Heroku in this URL: http://tweegle.herokuapp.com/. We need to make some changes in other to achieve that.

Socket.io

To add Socket.io support to our code in Heroku we need to add the following code:

io.configure(function () {
  io.set("transports", ["xhr-polling"]);
  io.set("polling duration", 10);
});

Redis

To adapt your project to Redis you need to follow these indications in the Heroku documentation. There is a special section to Node.js applications.

You only need to modify your code this way:


var redis = require('redis-url').connect(process.env.REDISTOGO_URL);

And modify your package.json file adding this line:


"redis-url": "0.1.0"

If you want to take a look at the code, it’s uploaded into my GitHub account. Feel free to copy or modify it.

 
7 comentarios

Publicado por en 21 abril, 2012 en web

 

Etiquetas: , , , , , ,

7 Respuestas a “Basic Node.js and Backbone.js application IV. Socket.io and Redis support

  1. Kaycee Shih

    23 abril, 2012 at 12:21 am

    I was just searching for this info for a while. After six hours of continuous Googleing, at last I got it in your site. I wonder what’s the lack of Google strategy that do not rank this type of informative sites in top of the list. Normally the top websites are full of garbage.

     

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

 
A %d blogueros les gusta esto: