Node.js and Socket.io – A basic chat application using websockets

Installation (Ubuntu & Windows)

I’m using an Ubuntu 12.04 LTS server, but any OS will do.
To install Node.js on Ubuntu, it’s fairly easy.

A few commands and you can start developing.

sudo apt-get install python-software-properties
sudo add-apt-repository ppa:chris-lea/node.js
sudo apt-get update
sudo apt-get install nodejs npm

If you’re running Windows, you can simply use the installer.

Note that from here, I’ll be working on Ubuntu 12.04 using a terminal.

Downloading dependencies

I’m going to use Socket.io for cross-browser websockets, so we need to install this.

First, cd to the directory of your application.
Then create a file called “package.json”. This file will tell us a bit about the application we’ll be writing.

Add the following content and save the file.

{
  "name": "node-chat",
  "version": "0.0.1",
  "dependencies": {
    "express": "3.x",
    "socket.io": "latest"
  },
  "engines": {
    "node": "0.8.x",
    "npm": "1.1.x"
  }
}

Then we can install all of our dependencies automatically using npm. (Node Packaged Modules)

npm install socket.io

This will fetch the dependencies that we’ve defined in our package.json file.
Currently, we’re using both Socket.io and Express.

Once that’s done you should have a new folder “node_modules”. Now we can create the actual application.

Getting stuff done (server-side)

Let’s first code the server. Create a new JavaScript file. I named mine “server.js”.

First let me show you what we will add to this file. I’ll explain it later.

var port = 5000;
var app = require('express')();
var server = require('http').createServer(app);
var io = require('socket.io').listen(server);

console.log("Listening on port " + port);
server.listen(port);

// routing
app.get('/', function (req, res) {
  res.sendfile(__dirname + '/chat.html');
});

// usernames which are currently connected to the chat
var usernames = {};

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

	// when the client emits 'sendchat', this listens and executes
	socket.on('sendchat', function (data) {
		// we tell the client to execute 'updatechat' with 2 parameters
		io.sockets.emit('updatechat', socket.username, data);
	});

	// when the client emits 'adduser', this listens and executes
	socket.on('adduser', function(username){
		// we store the username in the socket session for this client
		socket.username = username;
		// add the client's username to the global list
		usernames[username] = username;
		// echo to client they've connected
		socket.emit('updatechat', 'SERVER', 'you have connected');
		// echo globally (all clients) that a person has connected
		socket.broadcast.emit('updatechat', 'SERVER', username + ' has connected');
		// update the list of users in chat, client-side
		io.sockets.emit('updateusers', usernames);
	});

	// when the user disconnects.. perform this
	socket.on('disconnect', function(){
		// remove the username from global usernames list
		delete usernames[socket.username];
		// update list of users in chat, client-side
		io.sockets.emit('updateusers', usernames);
		// echo globally that this client has left
		socket.broadcast.emit('updatechat', 'SERVER', socket.username + ' has disconnected');
	});
});

It’s not that hard really.
First we define a few variables.

  • A port number
  • The application itself (using Express)
  • A server that will listen to requests
  • A socket.io variable that will handle websockets
  • An array to keep the usernames of the connected users

Then make the server listen to incoming requests simply by calling

server.listen(port);

We then set the routing for our Express application.
This will send the chat.html file to the client when it tries to get the index page of our application.

// routing
app.get('/', function (req, res) {
  res.sendfile(__dirname + '/chat.html');
});

Then we can start binding events.
Socket.io has a basic event “connection”. This will always trigger when a new user connects to the server.

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

Inside that function, you can bind other events. Eventss can be user defined.
I’m not going to explain all of them.

Things should be pretty straightforward if you know that

  1. socket.on('', function(data)); will bind to a certain event.
  2. io.sockets.emit('', data); will send an event with data to everyone that’s currently connected.

On to the client

Again, I will first show you what’s in the “chat.html” file that our application will serve.

<script src="/socket.io/socket.io.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
<script>
        var URL = window.location.protocol + "//" + window.location.host;
        console.log("Connecting to " + URL);
        var socket = io.connect(URL);

        // on connection to server, ask for user's name with an anonymous callback
        socket.on('connect', function(){
                // call the server-side function 'adduser' and send one parameter (value of prompt)
                socket.emit('adduser', prompt("What's your name?"));
        });

        // listener, whenever the server emits 'updatechat', this updates the chat body
        socket.on('updatechat', function (username, data) {
                $('#conversation').append('<b>'+username + ':</b> ' + data + '<br>');
        });

        // listener, whenever the server emits 'updateusers', this updates the username list
        socket.on('updateusers', function(data) {
                $('#users').empty();
                $.each(data, function(key, value) {
                        $('#users').append('<div>' + key + '</div>');
                });
        });

        // on load of page
        $(function(){
                // when the client clicks SEND
                $('#datasend').click( function() {
                        var message = $('#data').val();
                        $('#data').val('');
                        // tell server to execute 'sendchat' and send along one parameter
                        socket.emit('sendchat', message);
                });

                // when the client hits ENTER on their keyboard
                $('#data').keypress(function(e) {
                        if(e.which == 13) {
                                $(this).blur();
                                $('#datasend').focus().click();
                        }
                });
        });

</script>
<div style="float:left;width:100px;border-right:1px solid black;height:300px;padding:10px;overflow:scroll-y;">
        <b>USERS</b>
        <div id="users"></div>
</div>
<div style="float:left;width:300px;height:250px;overflow:scroll-y;padding:10px;">
        <div id="conversation"></div>
        <input id="data" style="width:200px;" />
        <input type="button" id="datasend" value="send" />
</div>

The HTML is not really important here.

Here we do pretty much the same thing as on the server.
Listening to events and sending events. It’s really not much more then that.

I’ll leave it up to you to figure out the client code. If you have some knowledge of JavaScript and JQuery, this should be easy.

Running your application

Just make sure you cd into the directory where your application resides.
Then call

node server.js

Replacing server.js with the file where you’ve written your server code.

It should now run, and you can browse to your application using your favorite webbrowser. (Just remember to use to the correct port)

Michiel De Mey

Full-time geek, Full Stack Engineer and Full Metal Hero. NodeJs, AngularJs, API design, WebSockets, WebSec & IoT enthusiast. Former San Francisco resident.

More Posts - Website - Twitter - Facebook - LinkedIn - Google Plus