Getting Started With WebSockets

Posted in

How often do you use a chat application in your web browser? Have you ever wondered how it functions differently than an average website? In this article, we’ll introduce what WebSockets are and how they improve regular HTTP API traffic to enable real-time bidirectional communication. We’ll then outline how to program a basic local WebSocket server and call it from Firecamp in a few simple steps.

Understanding WebSockets

Imagine an online multi-player game where the leaderboard is constantly changing on the server. Now, what’s the best way to keep it updated? We could either tell users to refresh the page manually or program the leaderboard to pull updates every few seconds. But both these options aren’t ideal for real-time data — that’s where WebSockets come in.

WebSocket is a bidirectional protocol for communication between the client and the server. It was standardized by IETF in 2011 as RFC6455 and is fully compatible with HTTP. This enables real-time applications such as chatting, notification, live feed, multi-player gaming, and many other use cases. WebSockets are often referred to as full-duplex connections. This is a term borrowed from telecommunications that defines how a telephone line works where both parties can support talk simultaneously.

How WebSockets Function

Many applications require a model where the client sends the initial request, after which the server delivers a stream of new data in real-time. In the case of a chat application, a server may also need to forward messages to multiple clients, as in group messaging. WebSockets solve the problem of having to connect to the server again and again to retrieve new messages. With WebSockets, the client and server can continue to communicate in real-time without making the request again and again.

The first step is for the client to send an HTTP request asking to open a connection. If the server agrees, it’ll send the 101 Switching Protocol response to the client, meaning the handshake is complete. A TCP/IP connection is opened, allowing the bidirectional connection to pass information between the two parties with very low latency. The connection will stay open until one of the parties drops off, and the TCP resources can be unallocated.

WebSocket is an HTTP upgrade. If you want to use the WebSocket protocol, you send a header to the webserver mentioning the upgrade, and further requests use the same TCP connection used to make the first connection.

Why Were WebSockets Introduced?

Let’s go back to 1995, when HTTP 1.0 was introduced. It used TCP methods to communicate and was dependent on request-response models. In other words, the client always makes a request, and the server responds only to that request.

This model worked great and is still working perfectly for many use cases. But TCP is expensive — it’s affordable when you have to get only one or two files. But if you want to fetch, say, thirty files, you’ll have to make thirty separate requests, and the server must process that same request thirty times. Opening and closing the connection this many times is costly and inefficient.

The above problem was resolved in HTTP 1.1 very smartly. Here we make one TCP connection and leave it open. Clients make all requests under this TCP connection and only close the connection when the user is finished. All of this was possible by using the keep-alive header. This was a good solution, but there are occasions when you need real-time interaction from the server. There is some information that the server needs to send despite you requesting the server as a client.

Many solutions like long-polling, short-polling, and WebSockets were introduced to resolve the above problem. But WebSockets is the dominant one. WebSockets uses HTTP 1.1 and its persistent TCP connection as a vehicle for bi-directional communication. Now they both are aware of each other, it means the system is no longer stateless; it’s stateful, right? Because the server and clients are aware of each other, it becomes stateful.

Working With WebSockets

We do the same thing with WebSockets — the client starts with an HTTP request. The client performs a WebSocket handshake request, which involves exchanging a little bit of information. This handshake will first occur with the server. The server responds whether it supports WebSockets or not. After the connection is detached from HTTP and shifted to WebSocket or WS, both the client or server can make a request or respond, as they both have access to the API of an underlying TCP connection.

Now let’s talk about the WebSocket handshake. When we talk about handshakes, we first must understand the protocol (ws:// and wss://). The first request is a standard HTTP GET request for the persistent TCP connection. There’s one special header which is called upgrade in the request. The server accepts the requests, and if the server understands the upgrade header and the client is trying to upgrade the HTTP 1.1 connection to something else (WebSocket in this case). The server will reply with 101 which means Switching Protocol. This handshake makes the TCP persistent.

  • Socket.io
  • WS
  • Sockjs
  • WebSocket Node
  • Socket Cluster
  • Feathers
  • Faye-websocket-node
  • Websocket as promised

Creating A WebSocket Server

Now, let’s walk through how to set up a WebSocket server.

Step 1: Prerequisites

Step 2: Project Setup

Open your Terminal and create a folder named websockets using the below command:

mkdir websockets
cd websockets

Once you’re in the folder, initialize your node project using the below command:

npm init -y

Now, install the package for WebSocket:

npm install ws

Step 3: WebSocket Server Setup

Now inside the folder websockets, create a new file index.js and paste the below code:

const WebSocket = require("ws");
const wss = new WebSocket.Server({port : 8082});

wss.on(
     "connection", ws => {
          console.log("New Client Connected");
          ws.on(
               "message", data => {
                    console.log(`Client Has send us the data: ${data}`);
                    ws.send("We have recieved a message");
               })

          ws.on("close", () => {
               console.log("Client has disconnected!");
          })
});

Code Explanation:

I’ll break the code into three parts so that it’s easy to understand.

const WebSocket = require("ws");
const wss = new WebSocket.Server({port : 8082});

In this part of the code, we’re importing the ws package, and the constant wss stands for the WebSocket Server used to initialize the server on port 8082.

 "connection", ws => {
          console.log("New Client Connected");
          ws.on(
               "message", data => {
                    console.log(`Client Has send us the data: ${data}`);
                    ws.send(`We have recieved a message: ${data}`);
               })

Now, we have event connection. So, whenever a client is connected, the connection event is called, and it’ll log a message on the terminal New Client Connected.

After the connection, whenever the client tries to send a message, the event message is called, and it’ll log what the client has sent. In response, we have ws.send to send the reply to the client.

ws.on("close", () => {
               console.log("Client has disconnected!");
          })

Lastly, we have the event close. When the client closes the WebSocket connection, this event is called.

Step 4: Testing the WebSocket

Now, open the Firecamp application and click on the WebSocket option. Why Firecamp? Because it natively supports WebSocket connections.

In Terminal, type node index.js to start the server.

Back in Firecamp, click on Websocket to open a new tab. Then, paste this URL ws://localhost:8082 and click on Connect. Enter any message you want in the message box and click on the send button. You should see the below output:

This is one way to create WebSocket connections. Keep in mind this is an elementary tutorial to working with WebSockets. To implement this on the front-end of a web application, you can use JavaScript functions like ws.send to send the message and ws.onmessage to receive the message from the server or the other end.

When To Use WebSockets

In this article, we covered the basics of WebSockets and how they function. We also demonstrated how to create a WebSocket with a short tutorial.

You might be wondering: why do we need a full-duplex setup? Well, chatting is an excellent example since it doesn’t fit the classical request and response model. WebSockets can be used for many other use cases, too. For instance, if you use a stock market app, the real-time data is likely being transferred through WebSockets. Often, developers also use polling as a fallback method to ensure the client and the server are synced.

In other words, when you want to keep a persistent connection, enable bidirectional communication, automatically receive responses from the server, and achieve real-time data, then WebSockets are a good option.