Simple Chat – Node.js + WebSockets

One of the best use cases for Node.js is real-time applications that handle lots of small requests simultaneously. A perfect example of this is a small chat application that allows multiple users to connect and send messages to each other. So today we are going to build this.

Simple Chat

Check out the live version.

We are going to be utilizing a technology called WebSockets, which will allow us to easily communicate between all of the users of our application. We are utilizing WebSockets via a Node module called Socket.IO. However, before we can dig into all the communications we are going to need some Node code.

For static content, we are using Express. May be a little overkill, but it does the job. The base app.js file will look like so:

var express = require(‘express’);
var app = express();
var server = require(‘http’).createServer(app);

server.listen(80);

app.use("/", express.static(__dirname + ‘/public’));

Nothing special. What we need now though is some Socket.IO action. We need to accept an incoming message then blast it out to everyone else that is listening to our server. Thankfully it is a small tweak on the server-side:

var express = require(‘express’);
var app = express();
var server = require(‘http’).createServer(app);
var io = require(‘socket.io’).listen(server);

server.listen(80);

app.use("/", express.static(__dirname + ‘/public’));

io.sockets.on(‘connection’, function (socket) {
  socket.on(‘msg’, function (data) {
    io.sockets.emit(‘new’, data);
  });
});

Yeap, a require statement and two callbacks later we have our server-side code. Basically what this is doing is waiting for a connection, then when a connection is established it subscribes to the “msg” event that happens when a client sends a message to the server. When this happens, we send the message to all connected clients, or “sockets” as they are called in this case. Simple stuff.

The client is a bit more complicated though. Let’s start with the HTML, which is pretty straight-forward.

<!DOCTYPE HTML>
<html>
  <head>
    <title>Simple Chat</title>
    <script type="text/javascript" src="/socket.io/socket.io.js"></script>
    <script
     type="text/javascript"
     src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js">
    </script>
  </head>
  <body>
    <div id="wrapper">
      <h1>Simple Chat</h1>
      <div id="messages"></div>
      <div class="nic">
        Your Name
        <input id="name" name="name" type="text"/>
      </div>
      <textarea id="message"></textarea>
      <input id="send" type="submit" value="Send"/>
    </div>
  </body>
</html>

The important bit here is the inclusion of /socket.io/socket.io.js. This is the client-side piece of socket.io, and will provide us with a simple way to communicate with our server. The coolest part is that the socket.io Node module sets up this route for us on the server, so we don’t have to do anything server-side to get this route to work.

To organize our chat code, we are going to create a JavaScript module which will provide a single, global instance to utilize. To start, let’s just get the module code:

//Create a chat module to use.
(function () {
  window.Chat = {
  };
}());

This will create a single instance of the Chat object in the global scope. However, we are going to need our Chat object to do something. Initialization is always pretty important, so we can add that next.

//Create a chat module to use.
(function () {
  window.Chat = {
    socket : null,
 
    initialize : function(socketURL) {
      this.socket = io.connect(socketURL);

      //Send message on button click or enter
      $(‘#send’).click(function() {
        Chat.send();
      });

      $(‘#message’).keyup(function(evt) {
        if ((evt.keyCode || evt.which) == 13) {
          Chat.send();
          return false;
        }
      });

      //Process any incoming messages
      this.socket.on(‘new’, this.add);
    }
  };
}());

In the initialize method, we are setting up the socket.io connection, subscribing to the new event, and making sure the send button and enter key do something productive. There is just one problem here, we don’t have an add function for the socket.on call to use. Let’s add that.

//Create a chat module to use.
(function () {
  window.Chat = {
    socket : null,
 
    initialize : function(socketURL) {
      this.socket = io.connect(socketURL);

      //Send message on button click or enter
      $(‘#send’).click(function() {
        Chat.send();
      });

      $(‘#message’).keyup(function(evt) {
        if ((evt.keyCode || evt.which) == 13) {
          Chat.send();
          return false;
        }
      });

      //Process any incoming messages
      this.socket.on(‘new’, this.add);
    },

    //Adds a new message to the chat.
    add : function(data) {
      var name = data.name || ‘anonymous’;
      var msg = $(‘<div class="msg"></div>’)
        .append(‘<span class="name">’ + name + ‘</span>: ‘)
        .append(‘<span class="text">’ + data.msg + ‘</span>’);

      $(‘#messages’)
        .append(msg)
        .animate({scrollTop: $(‘#messages’).prop(‘scrollHeight’)}, 0);
    }
  };
}());

Take some message data and add it to the DOM, that’s all we are doing here. Nothing special.

The final piece to this puzzle is actually sending the data.

//Create a chat module to use.
(function () {
  window.Chat = {
    socket : null,
 
    initialize : function(socketURL) {
      this.socket = io.connect(socketURL);

      //Send message on button click or enter
      $(‘#send’).click(function() {
        Chat.send();
      });

      $(‘#message’).keyup(function(evt) {
        if ((evt.keyCode || evt.which) == 13) {
          Chat.send();
          return false;
        }
      });

      //Process any incoming messages
      this.socket.on(‘new’, this.add);
    },

    //Adds a new message to the chat.
    add : function(data) {
      var name = data.name || ‘anonymous’;
      var msg = $(‘<div class="msg"></div>’)
        .append(‘<span class="name">’ + name + ‘</span>: ‘)
        .append(‘<span class="text">’ + data.msg + ‘</span>’);

      $(‘#messages’)
        .append(msg)
        .animate({scrollTop: $(‘#messages’).prop(‘scrollHeight’)}, 0);
    },

    //Sends a message to the server,
    //then clears it from the textarea
    send : function() {
      this.socket.emit(‘msg’, {
        name: $(‘#name’).val(),
        msg: $(‘#message’).val()
      });

      $(‘#message’).val();
    }
  };
}());

With socket.io you do two things: listen to events and trigger events. You listen with on (as we have seen), and you trigger events with the emit method. So when a message is ready to be sent, all we have to do is “emit” it with the message data. It will then be picked up on the server and emit it back out to all the sockets connected.

The only thing left to do is include it in the HTML and initialize it.

<!DOCTYPE HTML>
<html>
  <head>
    <title>Simple Chat</title>
    <script type="text/javascript" src="/socket.io/socket.io.js"></script>
    <script
     type="text/javascript"
     src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js">
    </script>
    <script type="text/javascript" src="chat.js"></script>
  </head>
  <body>
    <div id="wrapper">
      <h1>Simple Chat</h1>
      <div id="messages"></div>
      <div class="nic">
        Your Name
        <input id="name" name="name" type="text"/>
      </div>
      <textarea id="message"></textarea>
      <input id="send" type="submit" value="Send"/>
    </div>
    <script type="text/javascript">
      $(document).ready(function() {
        Chat.initialize(‘http://localhost/’);
      });
    </script>
  </body>
</html>

There it is, a complete chat application. If you run the Node script, it will start up and let you know socket.io is ready. Then you can bring up localhost and start chatting with…well, yourself if you run it locally. I have included all the code in a ZIP (or you can get it from github), as well as the addition of a little bit of “style” so it looks a little better. Don’t forget to npm install!

Hopefully this has been an informative, quick introduction to using WebSockets in Node.js. Just remember, when you need coding help, all you have to do is Switch On The Code.

Leave a Reply

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