Full-duplex communication over a single TCP connection.

Artist’s rendition.

My first experience using web sockets was in an app I built during a web development boot camp. The app was our introduction to the JavaScript framework React, and simulated a scheduler for making interview appointments. At first, the app handled updates to the scheduled appointments display through making an asynchronous Axios put request to the server, which updated the database and then returned the updated information, all through a standard HTTP request/response pattern.

However, it was soon pointed out to me that if I had the application running on multiple computers or even open in multiple windows on the same computer, then the updates made through this process would not be visible in real time — they would not appear until the page had been refreshed. While not a huge deal-breaker, this was not ideal behaviour. How could we make the appointment information update in real time across multiple browsers?

Enter Web Sockets.

Mathematical!

Initially, transmission of data over web protocols was limited to a request/response model. That is, the client had to request some data and the server would then send that data. At the time, this worked for the needs of the internet, but as applications stated to move to real-time implementations it became clear that a faster communication model was required.

The first attempt to create a lower-latency communication standard was known as long-polling This consisted of keeping the connection made after an initial HTTP request open, in order to allow the server to respond at a later time. This was essentially the precursor to WebSockets. For small applications, this seemed like a possible solution and long-polling did solve certain issues such as allowing a server to send back more than one piece of data. It also virtually eliminated instances of the server sending back empty response due to lack of data.

A depiction of a standard HTTP exchange between client and server. Source: [WebSockets — A Conceptual Deep Dive](https://ably.com/topic/websockets)

However, for larger applications with more users and requests and a larger database long-polling could become a very resource intensive solution and was not well suited for applications that require low latency. It also still required a connection setup and frequent request-response exchanges. A faster protocol was needed; one that allowed communication between client and server down to the nearest millisecond.

The WebSocket protocol is a stateful communication protocol that functions over a TCP connection. Initially, an HTTP handshake is made between the participating client and server but is then moved to the WebSocket protocol — assuming both parties agree to do so — and this protocol is used to continue the connection. This enables both client and server to continue to communicate in a full-duplex, persistent connection, meaning the connection is maintained for as long as the application continues running.

In short, this allows for near-instantaneous communication between client and server without requiring the usual cycle of request-response that had been the previous standard of network communication. This enabled all sorts of previously impossible real-time communication across the internet.

A depiction of the WebSocket protocol. Source: [WebSockets — A Conceptual Deep Dive](https://ably.com/topic/websockets)

As just a few examples, WebSockets have allowed things like online multiplayer games, collaborative code-editing, online drawing/drafting, real-time to-do apps with multiple users and much, much more.

Setting up a WebSocket

To return to the example I used at the beginning of the article, implementing WebSockets into my scheduler app allowed the app to be updated in real-time while open on any number of different computers.

The Scheduler App

(If you’re interested, you can view my Netlify-deployed scheduler app here to see its behaviour. Give it about 10 seconds for the Heroku-deployed server to wake up.)

This app uses a WebSocket set up entirely using the WebSocket API built into JavaScript and creating the WebSocket connection on the client-side is as simple as writing the line:

const socket = new WebSocket(server_url);

*(with server_url being whatever the server’s url is)

However, there are also many libraries that can be used to set up a WebSocket connection as well. One of the most commonly used and minimalist is Socket.io, and I will be using this as a very simple example of how to set up a WebSocket-enabled application, in this case a chat app.

The finished chat app. Thanks to The Net Ninja for the tutorial.

Creating this app is as simple as building out 3 files:

The server is built using Express and just the server setup can be done in about 15 minutes for both setup and writing the code. (For a quick and easy guide on how to setup an Express server, read this article.)

index.js is the server file, while chat.js and index.html make up the client-side files that are sent to the browser (alongside a CSS stylesheet that isn’t shown).

Socket.io can be installed for the server using npm with the command line input:

npm install socket.io

and included in the index.js server file:

const socket = require('socket.io');

On the client side, all that is needed is the following line inside the <head> tag of index.html:

<script src="/socket.io/socket.io.js"></script>

And this inside the <body> element:

<script src="/chat.js"></script>

Now, inside index.js the socket is created for the server:

const io = socket(server);

Next, a callback function to be fired upon connection by a client is defined within the same file:

io.on('connection', (socket) => {  console.log('Made socket connection. Socket ID: ', socket.id);});

On the client side, inside chat.js, all that is needed is the line:

const socket = io.connect(`http://localhost:4000`);

With just those lines of code, a WebSocket connection can be created and the following is printed to the console when a browser visits localhost:4000:

Made socket connection. Socket ID: PM3rH7OBBKYl2RrvAAAA

*Every socket connection has a unique ID that can identify it; a new ID is created for each new connection. This ensures that data can only be sent between client and server through already approved connections.

The rest of the code shown above allows the functionality of sending and receiving messages, as well as displaying when the other user is typing. All of this is handled in real time and enabled by the WebSocket protocol.

For a fun exercise, try and go over the rest of the code above and figure out how it all interacts now that you understand the basics of a WebSocket connection. Or, if you’d like to build this app from scratch, follow along with this excellent tutorial series by The Net Ninja (don’t forget to like and subscribe).

Socket.io is just one example of a WebSocket library. Other libraries include:

Paid and Managed Solutions

There are also many companies offering bundled solutions for WebSocket management. Most of these services offer free tiers that scale up into paid options depending on the amount of connections and messages that a given app requires. One of the most popular is Pusher, which offers 3 main products: Chatkit, Channels and Beams, which specialize in in-app chat, scalable realtime features and push notifications for mobile, respectively.

The advantage of using a service like Pusher is in their already developed library of APIs designed for specific purposes. They allow developers to tap into a rich set of features without having to worry too much about every single thing going on under the hood. Primarily, these APIs communicate through WebSockets, though they also have fallback options in the case that WebSockets are not available on the client’s machine. Pusher also offers these services across most commonly used web development languages, which increases the amount of cross-platform development that is available. An event-based abstraction enables almost any client or server, on any stack, to trigger UI interactions.

Pusher offers tutorials in how to use its services to develop specific features for almost every imaginable application, from server health monitoring to real-time map updates for food delivery apps. At last check, there were 543 different tutorials available on their website.

For applications that need a large scale and the ability to handle many connections simultaneously, paid management solutions seem like an excellent way to integrate WebSockets into the app flow.

In summary, Web Sockets:

  • Came about due to a need for lower latency data exchange.
  • Allow real-time interactive communication between the client and server.
  • Are extremely fast and lightweight.
  • Do not require an HTTP request in order to send a response to a connected client.
  • Are widely utilized across the internet for real time interaction.
  • Can be utilized through the integrated WebSocket API or through one of many free libraries.
  • Can be utilized as part of a hosted service such as Pusher.

Full Stack Web Dev Student @ Lighthouse Labs — Vancouver, BC

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store