In this article, we will learn about websockets, what is it, how do we use it and much more. We will also create a NodeJS application demonstrating how to work with websockets and also build another NodeJS application around one the most talked about use case of websockets, a chat application.

Also checkout how to Implement CRUD in NodeJS with Express and MongoDB here.

What are WebSockets?

Before understanding websockets, lets first understand how a http protocol works which will aid us in understanding websockets better.

HTTP protocol

Whenever we hit any url in browser, take for example google.com, the request goes to a backend server with the help of http or https communication protocol, making a TCP connection between you the client and the server. Now for every request we make there is a response in return, and once the response is received the connection is closed. So for every http request TCP connection is created and once the response is received that connection is closed.

Now let’s take a example of sports website, which constantly has to update scores of a live sports match. How do you think this can be achieved. If you follow the http protocol, we will either have to hit refresh constantly to get the updated score or we can set some interval for polling the server every few seconds. Do you think both of these cases are ideal ?

This is where websockets come into play.

WebSockets

Similar to http, websocket also involves a client and a server, but here we get a bi-directional flow of data and the TCP connection stays open until the client or server disconnects from it. If we take the above example of sports website, with the help of websockets we can bypass making multiple server requests to get live score, TCP connection will remain open between the client and the server and the client will keep receiving updated scores as and when its updated and passed from backend.

How it works is, first client makes a Get request to the websocket server which in return sends a status code 101 switching protocols. From this point on our connection is established between the client and the server, also called as the handshake. Now both server and client can communicated with each other through messages which can contain any form of data. Now this connection remains open until the server or the client closes it. This is a simplest explanation we can give of websockets.

Let’s get a deeper understanding by building a simple application demonstrating how it works.

Building WebSocket server in NodeJS

Now let’s see how we can build a websocket server in NodeJS.

Let’s initialize a new project with the help of a following command

npm init

This will give us a package.json file in our root folder.

To use websockets, we have a package in node which we can be install with the help of below command.

npm install ws

Now let’s use this node module to create a websocket server and listen to requests

Create a new index.js file with the following code

const webSocket = require('ws')

const server = new webSocket.Server({port:'8080'})

server.on('connection', socket => {
    
    console.log('Client connected')
    
    socket.on('message', message => {
        socket.send(`We received your ${message}`)
    })
    
    socket.on('close', (event) => {
        console.log('Client disconnected')
    })

})

console.log('socket initialized on port 8080')

Line 1: Importing the ws package to implement websocket connection

Line 3: similar to how we create a http server, here we are creating a websocket server which will listen on port 8080

Line 5: websockets are event based, and here we are listening to a connection event which is triggered when any client connects to it. This connection will stay open until we close it, either from client or server.

Line 9: Here we are listening to a message event from client, and sending the same message back, acknowledging the message.

Line 13: Finally we have our close event, which is triggered when the client requests to close the connection.

This is it, this is how we create a websocket server, simple right!!

Let’s see how a client can connect to it.

Connecting to a Websocket server

Create a new file index.html with the following code

<!DOCTYPE html>
<html>
<head>
    <meta charset='utf-8'>
    <meta http-equiv='X-UA-Compatible' content='IE=edge'>
</head>
<body>
    <button onclick="sendmessage()">Send Message</button>
    <button onclick="disconnect()">Disconnect</button>
</body>
<script>
    const socket = new WebSocket('ws://localhost:8080')

    socket.onmessage = ({data}) => {
        console.log("Message from socket server: ", data)
    };

    const disconnect = () => {
        socket.close()
    }

    const sendmessage = () => {
        socket.send('Hello')
    }
</script>
</html>

Line 8-9: Here we have created two buttons which will invoke respective functions on click.

Line 12: Here we are creating a new websocket connection by connecting to the server we created above. JavaScript has inbuilt WebSocket function to support this.

Line 14-16: Similar to the server, here we are listening to a message event, which is trigged whenever server sends any message.

Line 18-20: here we have created a function, which closes the websocket connection and is triggered on click of a disconnect button.

Line 23-24: In this function, which is being invoked on click of a send message button, we are just sending a ‘Hello’ message to the server through the socket connection.

Testing the application

Let’s test our app and check if everything works.

Run index.js using ‘node index’ command and open index.html in browser.

websockets demo

Here in the browser we see that we are getting two buttons we created and also in network tab we can see the ws request being made to the server and we received a status code 101 switching protocols, this tells us that a handshake is successfully established between the sever and the client.

Also when we see the terminal for index.js , we get the below result

websocket client connected

As we have consoled in index.js, on connection we see ‘Client connected’ message in terminal.

Let’s hit send message button and see the result

As you can see, as we click the send message button, sendmessge fucntion is invoked and a ‘Hello’ message is sent to the server. Server catches this in message event and sends the response in return, which we are catching in client using socket.onmessage function and printing it in console which we see above.

Now let’s hit disconnect button and see the result

socket disconnect demo

Here, as we hit the disconnect button, client requests to close the connection using socket.close() function. Server catches this close event logging the message ‘Client disconnected’ as shown above.

Now we have closed the connection, let’s see if we are still able to send any message back to server.

disconnect demo

As we can see here, since the websocket connection is closed we are getting the above error when we click send message button.

Building a Chat App using WebSockets

Let’s now build a chat application with the help of websockets, which is one of the most talked about usecase of websockets.

Creating Websocket Server for Chat App

Create a new file name app.js with the following code.

const webSocket = require('ws')
const server = new webSocket.Server({port:'8080'})

server.on('connection', socket => {
    console.log('Client connected')
    socket.on('message', message => {
        server.clients.forEach(client=>{
            if(client.readyState === webSocket.OPEN)
                client.send(`${message}`)
        })
    })
})

console.log('socket initialized on port 8080')

Here the only change from the previous implementation is, we have added one extra block of code on

Line 7-9: Here on trigger a of message, we are iterating through all the clients and checking if the client state is OPEN, which basically tells if the client is connected, then we pass the received message to all the clients that satisfies the condition.

This is all we have to do in this case.

Creating WebSocket Clients for Chat App

lets create two html files named client1.html and client2.html with the following same code in both of them

<!DOCTYPE html>
<html>
<head>
    <meta charset='utf-8'>
    <meta http-equiv='X-UA-Compatible' content='IE=edge'>
</head>
<body>
    <input type="text" id="message">
    <button onclick="sendmessage()">Send</button>
    <div id="chatbox"></div>
</body>
<script>
    const socket = new WebSocket('ws://localhost:8080')

    socket.onmessage = ({data}) => {
        document.getElementById('chatbox').innerHTML += "<br/>"+data
    };

    const sendmessage = () => {
        message = document.getElementById('message').value
        socket.send('Client 1: ' + message)
        document.getElementById('message').value = ''
    }
</script>
</html>

Line 8-10: Here we are creating a input field to write down the messages and a send button which will invoke sendmessage() function and a div where all the messages will get populated.

Line 15-17: here we have our onmessage event where we are appending the incoming messages to the div we created.

Line 19-23: Here we are taking the value entered in input field and sending it as message from a respective client to the backend. Which in turn will send it to all the connected clients. In client2.html just change Line 21 to socket.send(‘Client 2: ‘ + message), to differentiate between the clients.

Running the Chat Application

Lets see the entire application in action.

Run the app.js file using the command ‘node app’ and open client1.html and client2.html in browser

Once we do that we get the below result in terminal

websockets 2 clients

As we opened two clients in browser we see that in terminal two clients are connected successfully.

Now let’s see if the chat functionality is working. Below is the result of what we have built.

As you can see we are successfully able to communicate between two clients using a websocket server.

Now ideally a application should contain a lot more features like authentication, user sessions, database and much more. This application is just to get the basic understanding of how websockets work and how we can use it to build application like these.

This completes our tutorial on Websockets implementation in NodeJS.

You can checkout full source code for this implementation here.

Leave a Reply

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