Node.js + socket.io short tutorial

About

Very shortly summarized: You can use Node.js + socket.io to enrich your websites with realtime applications like notifications, chat, events etc without a huge load on server side.

Node.js

“Node’s goal is to provide an easy way to build scalable network programs.”

Basically Node.js enables you to easily write server implementations using javascript. You need very little knowledge about server side development and you don’t need to make complex initializations etc, Node.js does these things for you. As a web developer you need quite little knowledge about Node, socket.io is the thing that you will be using more.

Read more from nodejs.org

socket.io

“Socket.IO aims to make realtime apps possible in every browser and mobile device, blurring the differences between the different transport mechanisms. It’s care-free realtime 100% in JavaScript.”

Socket.io makes it easy to send and receive data on both, client and server side in realtime. It uses Node.js on the server side for handling http requests. On client side, it works as a nice wrapper so that developer need to write only very little code in order to make lots of cool things. Http-connections are kept online continuously without polling, which means realtime applications without huge server side load.

Read more from socket.io

Browser support

Node.js browser support:

Desktop

  • Internet Explorer 5.5+
  • Safari 3+
  • Google Chrome 4+
  • Firefox 3+
  • Opera 10.61+

Mobile

  • iPhone Safari
  • iPad Safari
  • Android WebKit
  • WebOs WebKit

Server-side installation

Simple installation order:

  • Node.js
  • npm, “curl http://npmjs.org/install.sh | sh” should do the trick
  • socket.io, “npm install socket.io” does the install

Installing Node in linux

  • Download source
  • Extract source: “tar xvzf <file>”
  • Enter source directory
  • Configure: “./configure”. There might occur some errors etc, so you might have to install some extra libraries.
  • Compile: “make”
  • Install: “sudo make install”

After those steps you should be able to execute ”node”-command in terminal.

Installing npm

Node package manager installation should be very simple, just execute following in terminal: “curl http://npmjs.org/install.sh | sh”

Installing socket.io

Socket.io installation is very easy using npm. Simply execute ”npm install socket.io” and that’s it.

Development

Using Node.js and socket.io

Specific notes

Unfortunately the documentation is unfinished for both of them. So here are some very specific notes how to do different things.

send to specific socket(s)

If you need to send something to a specific user, you probably only know the user’s socket ID. You don’t usually have the socket itself. For this case I did not find any usefull documentation, so with bit of hacking I found a way (not pretty, but works):

/* in init phase we use io-named var (just for clarification here) */
var io = require("socket.io").listen(http);
/* get socket id somewhere else */
var id = socket.id;
/* send to socket which id we have */
io.sockets.sockets[id].emit(...);
/* you can also loop this and send to which ones you like */
for (var id in io.sockets.sockets)
{
    var socket = io.sockets.sockets[id];
    // do stuff with socket
}

broadcast to all including sender

When you receive message from a socket, you can broadcast some message to all others using ”socket.broadcast…()”. But when you want to broadcast to all including the sender it a different story. I didn’t find any function to do this, so it had to be done manually:

socket.emit(...);
socket.broadcast.emit(...);

Example

Simple implementation, you need to install Node.js and socket.io for this to work.

Includes following files:

  • index.html
  • client.css
  • client.js
  • server.js

server.js

You must execute this with “node”-command in terminal.

/*
 * Ip address and port where to listen for incoming connections.
 * Set ip as "0.0.0.0" to listen all.
 */
var host = "0.0.0.0";
var port = 8000;

/*
 * Initialize node and socket.io plus url parser and filesystem reader.
 */
var http = require("http").createServer(httpHandler);;
var io = require("socket.io").listen(http);
var url = require("url")
var fs = require("fs");

/* start listening incoming connections */
http.listen(port, host);
/* setup socket.io new connection events handler */
io.sockets.on("connection", ioConnection);

/*
 * Handle http requests here. Socket.io request are automatically served
 * before this.
 */
function httpHandler(request, response)
{
    var u = url.parse(request.url);
    console.log(request.method+": "+u.pathname);

    /* If this is a simple GET request into filesystem */
    if (request.method === "GET") httpFileServe(request, response, u.pathname);
    /* Not handling any other requests for now */
    else httpResponse404(response);
}

/*
 * Server file from filesystem.
 */
function httpFileServe(request, response, filename)
{
    if (filename.length == 0 || filename === "/") filename = "/index.html";
    console.log("serve file "+filename);

    /* Try sending the file, or 404 in errors */
    fs.readFile(__dirname+filename, function (err, data)
    {
        if (err) return httpResponse404(response);

        response.writeHead(200);
        response.end(data);
    });
}

/*
 * Wrapper for sending 404.
 */
function httpResponse404(response)
{
    response.writeHead(404);
    return response.end("File not found");
}

/*
 * Handle new connection here. This mostly means binding socket.io events.
 */
function ioConnection(socket)
{
    /*
     * In some cases you need the incoming socket and this was the only way
     * I found for relaying the socket to socket.io event functions
     */
    socket.on("disconnect", function() { ioDisconnect(socket) });
    socket.on("message", ioMessage);
    socket.on("event", function(event, data) { ioEvent(socket, event, data); });
}

/*
 * When user example closes tab on browser.
 */
function ioDisconnect(socket)
{
}

/*
 * A simple message from browser.
 */
function ioMessage(message)
{
    console.log(message);
}

/*
 * Event from browser.
 */
function ioEvent(socket, event, data)
{
    switch (event)
    {
    case "connect":
        break;

    case "ping":
        socket.emit("event", "pong", data);
        break;
    }
}

console.log("Server running");

client.js

This is the client side script run in user’s browser.

/* connect socket.io to server */
var host = "123.123.123.123";
var port = 8000;
var socket = io.connect("http://"+host+":"+port);

/*
 * Event from server.
 */
function ioEvent(event, data)
{
    switch(event)
    {
    case "pong":
        notify("pong: "+data.data);
        break;
    }
}

/*
 * Should be quite self-explanatory.
 */
function notify(msg)
{
    var o = $("<li>"+msg+"</li>").appendTo("#notifications");
    o.delay(5000).fadeOut(function() { $(this).remove(); });
}

$(document).ready(function()
{
    /* bind event handler to our socket */
    socket.on("event", ioEvent);

    /* when clicked, send event to server for processing */
    $("#ping").click(function()
    {
        console.log("send ping");
        socket.emit("event", "ping", { data: "data that was send as json when you clicked ping!" });
    });
});

index.html

<html><head><title>Node.js + socket.io</title>
<script type='text/javascript' src='http://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js'></script>   
<script src="/socket.io/socket.io.js"></script>
<script src="/client.js"></script>
<link type='text/css' rel='stylesheet' href='/client.css' />
</head>
<body>
<h1>Node.js + socket.io test page</h1>
<span id='ping'>Click here to send ping!</span>
<ul id='notifications'></ul>
</body>
</html>

client.css

#ping
{
    background: #e0e0e0;
    border: 1px solid #a0a0a0;
    cursor: default;
}

#notifications
{
    position: fixed;
    top: 10px;
    right: 10px;
    padding: 0;
    margin: 0;
    list-style-type: none;
}

#notifications li
{
    border: 1px solid black;
    padding: 5px;
    margin-bottom: 10px;
    width: 200px;
    background: #e0e0e0;
}

Leave a Reply

Your email address will not be published. Required fields are marked *


four × 1 =