Using WebSockets in Node.js

Node.js does not come with a default module for using WebSockets. While we have tried so far to avoid third-party solutions and just show you how to work with Vanilla node, this topic is complex enough to put writing a WebSocket handler from scratch well beyond the scope of the book. Therefore, for the remainder of this chapter, we will use the excellent socket.io library. We of course do not imply that this is what you should be using in your own work, and in the Chapter 6, Introducing Ionic, the Going further section at the end of the chapter, we will direct you to alternative solutions and reading materials for WebSockets.

Setting up our project

We will set up a separate project for this chapter, demonstrating how we can create a simple chat application that demonstrates the essentials of using WebSocket.

Create a separate project folder and name it chat-app. In this folder, create a blank file named app.js. Finally, open your terminal or the command prompt, go into the folder, and run the following:

npm init

Answer the questions prompted by Node.js and make sure that you specify app.js as the entry point for the application.

Installing socket.io

We will install socket.io, as always, by using our good friend npm. From your terminal, issue the following command:

npm install socket.io

That's it. We are now good to go. Let's start setting up our server! However, before we do that, let's start from the top and define a basic chat interface for us to play with.

Creating a chat interface

We are not creating the next WhatsApp (yet!). So, building a full-fledged chat interface is a bit beyond what we want to achieve in this chapter. Let's go for something basic, as illustrated in the next screenshot:

Creating a chat interface

To create this layout, create the index.html file in your project folder and insert a basic HTML setup inside it, as follows:

<!DOCTYPE html>
<html>
  <head >
    <meta charset="UTF-8">
    <title>Socket.IO chat application</title>
  </head>
  <body>
  </body>
</html>

We will now add some custom elements to this markup in order to get the layout we need for our chat to be nice and user friendly. First, import the Bootstrap CSS framework by inserting a link into href in the header:

<head lang="en">
  <meta charset="UTF-8">
  <title>Socket.IO chat application</title>
  <link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css"/>
</head>

Bootstrap, originally developed by Twitter, is a widely used framework that can be utilized to quickly build responsive web interfaces. As web design is beyond the scope of this book, we will use it in order to keep manual styling to a minimum. Don't worry if you are unfamiliar with the framework. It is very intuitive, and we will explain what you need to know along the way.

Next, let's add a Bootstrap container div to our interface, as follows:

<body>
  <div class="container"></div>
</body>

This is simply an organizational unit that Bootstrap uses to contain a set of UI elements inside a container so that the layout fits well on the screen being used.

Next, inside the container, let's add a chat-box, as follows:

  <div class="row">
    <div id="chat-box" class="well">
      <ul id="chat-view" class="list-unstyled"></ul>
    </div>
  </div>

The following are the three classes that are being used in the preceding code:

  • The row class, which is similar to the container class, is an organizational unit that confines the elements that it holds to a single row in the layout.
  • The well class, which creates a shaded container, make the elements it contains more visually distinct.
  • The list-unstyled class, which simplifies the ordinary HTML unordered list tag, removes, among other things, the bullet styling that appears next to elements.

The end result is shown in the following screenshot:

Creating a chat interface

Now, let's add the elements needed for users to enter their names and submit actual messages, as follows:

<form action="">
  <div class="row">
    <input type="text"
    id="chat-name"
    class="form-control"
    placeholder="Your name">
  </div>
  <div class="row">
    <input type="text"
    id="chat-message"
    class="form-control"
    placeholder="Enter message">
    <button id="chat-submit"
    type="submit"
    class="btn btn-default">Send
    </button>
  </div>
</form>

By now, you should be familiar with most of the UI elements and what they do, and the rest is nothing but a standard HTML form (note that we do not provide an action for the form itself; submissions will be handled dynamically through JavaScript instead). Note that we added some classes to the form elements. These are standard Bootstrap layout classes that are used to style the appearance of the elements themselves. They do not introduce any functionality in themselves, and as such, we do not need to deal with them in detail here.

That's it! If you open the file in your browser, you will see the following:

Creating a chat interface

The chat obviously does not really do anything at the present time. We will do something about this in a moment, but first, let's see how we can serve the HTML file that we just created directly from Node.js.

A basic file server

We now have an HTML file for our interface, which we would like the user to see whenever they connect to the app via their browser. To make this happen, we need to make our Node.js app listen to HTTP requests and then respond with the appropriate HTML file. Sounds familiar? Yep, it's time to reintroduce the Node.js HTTP module. Go ahead and add the following at the top of the app.js file:

var http = require('http');
var url = require('url');
var fs = require('fs');

We have already seen the first two modules. The third one, fs, is the standard module that is used to handle interactions with the file system. We will need this module in order to retrieve and serve the HTML file.

Let's create an HTTP server for this end. Add the following to app.js:

var server = http.createServer(function (req, res) {
  var parsedUrl = url.parse(req.url, true);
  switch (parsedUrl.pathname) {
    case '/':
    // Read the file into memory and push it to the client
    fs.readFile('index.html', function (err, content) {
      if (err) {
        res.writeHead(500);
        res.end();
      }
      else {
        res.writeHead(200, {'Content-Type': 'text/html'});
        res.end(content, 'utf-8');
      }
    });
    break;
  }
});

Let's go through what happens here. Upon receiving an HTTP request, our server will try to find a match for the path name of the request. If the path is for the root of the document hierarchy (signified by a normal slash), we want to serve the index.html document. If this is the requested path, the following happens:

  1. The readFile() method, which is part of the fs module, is invoked in order to load the index.html file.
  2. If the load fails (that is, if there was an I/O error), the server responds with status 500, indicating a server error.
  3. If the file is successfully loaded, we add its content (in this case, a string of HTML content) to the response payload, set the appropriate media type and code for the response, and serve it back to the client.

By default, a status 404 is served if the client tries to access any other part of the document hierarchy.

Let's see this in action. Add the following to the end of app.js:

server.listen(8080);

Start the server from your terminal, as follows:

node app.js

Open your browser and visit http://localhost:8080. You will see the following:

A basic file server
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.135.247.11