Skip to content

Part 2: Building the server with Node.js and Socket.io

Sergi Almar edited this page Nov 21, 2013 · 8 revisions

Creating the Node.js project

In order to have the skeleton of the project, we'll rely on express.js (the sinatra-like framework). Install express globally with the following command:

sudo npm install –g express

Now let's create an express based app called mobos-chat

express mobos-chat

The following structure will be created

   
create : mobos-chat
   create : mobos-chat/package.json
   create : mobos-chat/app.js
   create : mobos-chat/public
   create : mobos-chat/views
   create : mobos-chat/views/layout.jade
   create : mobos-chat/views/index.jade
   create : mobos-chat/public/images
   create : mobos-chat/routes
   create : mobos-chat/routes/index.js
   create : mobos-chat/routes/user.js
   create : mobos-chat/public/stylesheets
   create : mobos-chat/public/stylesheets/style.css
   create : mobos-chat/public/javascripts

Notice that a file called package.json containing the dependencies has been created. Execute npm install to add them to the project (check that the node_modules folder is created and contains the dependencies).

The app.js is the entry point to our application, it imports the required modules, defines some routings and creates the http server. Open and take a look at it. This should be enough to start our application.

Execute node app or npm start to start the app. Check that typing 'http://localhost:3000/' in your browser gives you the welcome page.

Adding Socket.io

By now, you should be familiar with packages.json. In order to add the Socket.io support we need to define it as a dependency in such file, open it and add: "socket.io" : "~0.9.16". Run npm install again to fetch the dependency.

Let's now create a module which will encapsulate the socket.io logic. Create a file called socket.js inside the routes folder.

This module will use the socket.io dependency that we have already defined. Import it in the module

var socketio = require('socket.io');

The modules contain logic private to the module itself, they encapsulate logic, but remember that they can also expose it using the CommonJS convention (with the exports variable). Let's expose a function called initializeso we can initialize it from another module:

exports.initialize = function(server) {
    io = socketio.listen(server);
}

We have added a server parameter (this will be the http server already created in the app.js file) and we are initialized socketio in order to start accepting connections. Now its time to use our module.

Using our Socket.io module

Open the app.js and add the module we just created var io = require('./routes/socket.js');. Remember we exposed an initialize function expecting an http server as a parameter. If you scroll at the end of the file, you will see how the http server is created (by default listening at the port 3000). Lets get a reference on that server so we can pass it to the module

var server = http.createServer(app).listen(app.get('port'), function(){
  console.log('Express server listening on port ' + app.get('port'));
});

You can now call the initialize function, passing the server parameter:

io.initialize(server);

Start the app again (node app) and check you see something like info - socket.io started on the console.

Handling events

Now we have the app already listening for WebSocket connections, but we need to handle the events (new connection, disconnection, messages...). Let's add a connection listener inside the initialize method:

io.sockets.on('connection', function(socket) {
   // All your handlers here, socket will be the connected client
});
  1. Provide a handler for the event 'user:setname'. This will be triggered by the client right after connecting. (Tip: remember socket.on('event', function (data) {}?). The message received will be something similar to {'nickname': 'sergi'}. Set the value to the socket session so we can remember the username and we don't force it to be send over and over again (hint: use socket.set). Broadcast a message like '{message:'sergi has joined!'} to all connected users.

  2. Provide a handler for the event 'user:message'. This event will be triggered when a user sends a message to the chat. The data will be a JSON similar to this: {'message':'Hey there'}. Broadcast the message to all the other clients adding the nickname to it (hint: use socket.get(var, function (err, nickname) {}) to get the previously stored nickname). The resulting message should be like {'message' : 'Hey there', 'nickname' : 'sergi'}

BONUS:

  1. Store the user names in an array var users = [];, store the name when they connect and remove them when they disconnect.