Node.js and socket.io – a basic tutorial

node-js

Level: advanced

Node.js itself is great. Let’s add socket.io and have possibilities, which formerly we could only dream of.

Node.js and socket.io

After presenting basics of node.js and how to work with databases, it’s time to reach for even more interesting things.

One of them certainly is socket.io. Simply establish a connection between our site (front end) and the node script, running on the server:

var socket = io.connect('//localhost:1337');

But let’s start from scratch with node.js and socket.io, step by step.

As first we can customize our configuration by adding elements necessary to work with sockets. More about basic config file you can check in the previous article.


var config = {};
config.db = {};
config.general = {}; // added

config.db.type = 'mysql';
config.db.charset = 'utf8';
 
config.db.username = 'user';
config.db.password = 'pass';
config.db.host = 'localhost';
config.db.dbname = 'node_tests'; // DB name

config.db.comments_tbl = 'comments';

// added
config.general.host = '//localhost'; // http://my.host.com etc
config.general.port = 1337;
config.general.debug = false; // debug mode on/off

// export
module.exports = config;

We added new configuration parameters. Today we won’t use databases; this configuration will be also useful to us in the next tutorial.

To start, we need only socket.io module. So let’s install it in our folder with code:

$ npm install socket.io

or if we want – globally”

$ npm -g install socket.io

Let’s code! We will create two simple parts – frontend and backend.

1. A HTML page

<!DOCTYPE html>
<html>
    <head>
        <title>Socket.io tests</title>

        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">

        <script src="https://code.jquery.com/jquery-1.11.2.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/1.3.2/socket.io.min.js"></script>

        <script>
            var socket = io.connect('//localhost:1337');

            // emit some data
            socket.emit("user_online_data", {
                data: {id: 1, name: "Tester", msg: "Hello!"}
            });

            // handle our events
            socket.on('welcome', function (data) {
                // process data from node script
                $('#messages').append('<li>' + data.message + '</li>');

                // emit data to node script
                socket.emit("sayhi", {
                    data: 'Hi node!'
                });
            });

            // another "event" we named "time"
            socket.on('time', function (data) {
                console.log(data);
                $('#messages').append('<li>' + data.time + '</li>');
            });

            // if someting went wront and node script sent error data
            socket.on('error', function () {
                console.error(arguments);
            });
        </script>
    </head>

    <body>
        <ul id="messages"></ul>
    </body>

</html>

The code from this file we can simply run in the browser, but this in a moment. We’ll also discuss whole code.

We still need the code working on the server side.


2. Node.js script (server) – test.js

/*
 * node.js and socket.io tests
 */

var http = require('http'),
    fs = require('fs'),
    index = fs.readFileSync(__dirname + '/index.html');

// setup
var config = require('./config.js');
var PORT = config.general.port;
var HOST = config.general.host;

// send html content to all requests
var app = http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/html'});
    res.end(index);
});

// socket.io server is listening ...
var io = require('socket.io').listen(app);

// sample function:
// send current time to all connected clients
function sendTime() {
    io.sockets.emit('time', {
        time: new Date().toJSON()
    });
}

// send current time every 10 secs
setInterval(sendTime, 10000);

// emit welcome message on connection
io.sockets.on('connection', function (socket) {
    socket.user_id = 0; // current user ID

    socket.emit('welcome', {message: 'Welcome!'});

    socket.on('sayhi', console.log); // just log data in console

    // process the data
    socket.on('user_online_data', function (data) {
        socket.user_id = data.mydata.id; // "socket scope"

        var name = data.mydata.name; // local scope
        console.log("#:" + socket.user_id + ", name: " + name);
    });
});

app.listen(PORT);

console.log('Server running at ' + HOST + ':' + PORT + '/');
// console.log('Debug: ' + config.main.debug);

We assume that both files are located in the same folder. In this way, the node server which we just wrote, will serve us content of our web page (index.html) via WWW. It happens in the line:

...
    index = fs.readFileSync(__dirname + '/index.html');

Assuming we have the socket.io module already installed (npm install socket.io), we can start our server.

Open command line, go to folder with code and run test.js script:

$ node test.js

Then simply open in web browser our web page (remember about the port), e.g.:

http://localhost:1337/

Now we should see served page, which will be updated every 10 seconds by data from our node.js server:

2015-04-27_1234

And in the console we should see the data sent from the client:

2015-04-27_1235

Clean, efficient communication and data exchange. That’s the beauty of node.js and socket.io!

What happens in the code

We used here basic elements necessary for efficient work with node.js and socket.io. Let’s discus them in sequence.

The index.html file

As first we add necessary libraries: socket.io.min.js and additionally – jQuery.

After connecting we go to the proper communication. Note: to connect properly remember about the port (for the code on client- and server- side must be the same).

We send the data using method emit as: socket.emit(“key_name”, { data });

In the further lines we handle the case of sending “welcome” message by the server:

socket.on('welcome', function (data) { ...

The next event we handle, is displaying detailed information about current time, send by the server every 10 seconds. This of course only something for demonstration:

...
socket.on('time', function (data) {
  console.log(data);
  $('#messages').append('<li>' + data.time + '</li>');
});
...

Now let’s talk about sever-side code

Server – test.js

The first thing here is “set up” of necessary modules:

var http = require('http'),
    fs = require('fs'),
    index = fs.readFileSync(__dirname + '/index.html');

The last line reads our index.html file, to serve content on the port configured for our server (here: 1337).

Certainly we don’t have to do it; usually when we develop web application, we have a separated code (e.g. based on PHP MVC framework). So the code for communication through socket.io we place e.g. in template of particular web page.

Then it’s enough to serve anything, e.g.:

var http = require('http'),
  index = "<html><body>Listening ...</body></html>";

Next operation in our code is to get settings and create the server.

Then we have the sendTime() function, called every 10 secs, which emits data – here the object with current date – as JSON.

And we go to the block of code that handles communication:

io.sockets.on('connection', function (socket) {
...

In case of successful socket.io connection, the code from this block will be executed. In our case it’s:

– send “welcome” message:

socket.emit('welcome', {message: 'Welcome!'});

– handle the “sayhi” event, emitted on client side:

socket.on('sayhi', console.log);

– at the end something more interesting – processing received data :

socket.on('user_online_data', function (data) {
  socket.user_id = data.mydata.id; // "socket scope"

  var name = data.mydata.name; // local scope
    console.log("User #:" + socket.user_id + ", name: " + name);
});

As we see, getting the data is very simple. We could also pay attention to the local variable (var) and a variable “within” the socket. For example when we want to use value of current user ID, in current connection, we can assign this value for the socket (socket.user_id = data.mydata.id).

Connection broken, disconnection

When we have our page opened in the browser, and we terminate server-side script (CTRL + C in console), certainly communication errors will occur.

Opening e.g. Firebug, we will see the failed calls:

node-js-socket-io

There are many attempts of reconnection. To limit this, simply change the line responsible for connection:

var socket = io.connect('//localhost:1337', {reconnection: false});

This will block attempts of reconnection.

Additionally, to handle disconnection case (e.g. user closed browser window) on server side, we use the disconnect event:

...
socket.on('disconnect', function() {
  if (socket.user_id > 0) {
    // if (config.general.debug) { console.log('Bye #: ' + socket.user_id); }
    // do some cleanups ...
  }
});

Full code of an example available here:

https://github.com/dominik-w/js_html5_com/tree/master/node-socket-io-tutorial

We talked here about basic elements, on which we can build our solutions based on node and socket.io. The next tutorial will be with practical example – real time comments implementation.

Node.js and socket.io – summary

Well – these are great technologies, what we should notice in today’s examples. Although it was still only basic information.

I also encourage you to check the documentation of socket.io:

http://socket.io/docs

Thank you!

Web and Mobile Software Developer, with years of experience. My biggest passions are programming, new technologies, e-commerce, as well sports, cars, and of course my family.

Facebook Twitter LinkedIn Google+ Skype Xing 

Share: Share on Facebook3Tweet about this on TwitterShare on Google+1Share on LinkedIn2Share on Tumblr0Digg thisEmail this to someonePin on Pinterest1
You can leave a response, or trackback from your own site.
  • Cronex

    io.connect is not defined.