Have you ever thought about how live updates work? I mean, if I'm talking to my friend, and he sends me a message, I get that message right away (usually). How does my client know when my friend's sent a message? Today, we're talking about WebSockets, the solution to live updates like messaging, real-time notifications, or referencing external site data, to name a few. So, without further ado...
What is a WebSocket?
Websockets are a bidirectional TCP communications protocol. They allow for real-time communication between the client and the server. They run on HTTP ports and support HTTP proxies by design, so while they're distinct from HTTP, they're fully compatible with it.
They work by establishing a listener for a specified event, keeping a connection open but not sending any data across it until the event happens. So, let's look into how that works with...
The WebSocket Protocol
The WebSocket protocol is a three step process which is what allows WebSockets to work the way they do. It involves:
- An opening handshake
- The client sends an HTTP request, asking the server to switch protocols
- The server sends back status code 101 on success, indicating that we've successfully opened a handshake
- Message exchange
- Now that the handshake is open, the client and server can freely send messages to each other
- Messages must be sent in a form of data both the client and server have agreed on, like JSON or XML.
- Closing the handshake
- Once we're done trading data, the handshake can be closed by either the server or client sending another HTTP request to do so
- Once that request succeeds, it's reflected by the other
If none of that makes sense, let's look into...
Why Use WebSockets?
Needless to say, the real-time communication between client and server allows for many possibilities, but let's say you're like me and things haven't clicked just yet. Can we get a practical example? Let's go back to our messaging app example.
Say I open WhatsApp to talk to my friend.
- I open a chat, and the messages get loaded.
- I send a message, maybe the refresh function gets called and my chat updates again, so I see any new messages sent since then.
- My friend sends a message, but what happens if I don't send one or reopen the chat?
- I just don't ever get that message without some kind of a refresh timer, and even then, it's not live!
How many messages could I get sent in the 30, 10, or even 5 seconds it takes for that automated refresh to hit? The issue is that my client is fully unaware of my friend's. It doesn't know when he sends a message. It doesn't know when to refresh. So, how do WebSockets help?
Let's take the above example, but implement WebSockets. Now, my client still doesn't know about my friend sending me messages, but the server does. So, we ask the server to listen for messages being sent. When my friend sends me something, the server says "oh! new data!" and sends it over to my client without being checked on! But this still sounds like a lot, so, how about an alternative, would that be better?
The Evil Alternative... Polling!
"Hey, do you have data? Any data yet? Now? How about now? Oh, hey, data!"
As it turns out, WebSockets were made for good reason; there's not much of a way to use strictly HTTP, which is one-way communication, to properly update things live. So, how might we get something like it? Essentially, we'd just constantly be sending data, in the form of requests, to the server. Just asking it if it has new data over and over, updating when it does, forever. This isn't great, because unlike WebSockets, which keep the connection open but doesn't send data unless necessary, we're constantly abusing the connection with repeated requests. This isn't exactly great for the network. But, WebSockets being pretty great aside, what happens when we hit an error?
What if the WebSocket fails?
First of all, let's say we did something wrong; sent bad data or something, and the WebSocket fails. The connection is terminated, and the user is left very confused as to what went wrong and why things aren't updating, which isn't a good user experience, and makes people not want to use our app. What can we do about this, you might ask? Well, that's what fallback methods are for!
There are two primary methods we can implement to fail "safely" instead of our above mentioned experience:
- Switch to a new connection!
- If the WebSocket connection fails, we can actually just... switch to another!
- This allows seamless continuation of the connection for the user without running into the "things just aren't working right" issue
- Implement custom error handling!
- Needless to say, hitting a connection issue with no info is kinda sucky, as a user. Our second connection might even fail, leaving us with an unhappy user once again.
- We should add custom handling for the errors, like messages or redirects, to let the user know what went wrong. This way, they aren't just guessing. Feedback is everything!
By doing these, it's a less jarring experience to run into an issue as a user. And we can even make the whole process easier on ourselves with (drum roll please)...
Libraries!
Libraries, like any other kind of library, aren't necessary, but add various functions and methods to make the whole thing a lot easier. You can implement WebSockets by creating a WebSocket object and connecting to it via an endpoint. But regardless, let's go over some popular ones and why you might use them:
- websockets/ws - noted as one of the fastest available libraries, if not the fastest.
- uNetworking/uWebSockets.js - recommended by socket.io as a plain WebSocket server implementation, though isn’t in the npm registry; can still be installed via an npm command found on their github
- SockJS - includes newest to oldest fallback methods
- SocketCluster/socketcluster - makes use of all CPU cores on your machine to potentially provide a massive boost to traffic handling
- socketio/socket.io (sorta) - notably not a plain WebSocket implementation; uses WebSockets where possible, but adds extra metadata to packets which makes socket.io and plain WebSockets incompatible, and doesn’t use WebSockets if not supported by the browser, in which case it falls back to HTTP; client attempts to reconnect if disconnected
These libraries can make working with WebSockets a much more pleasant experience, and libraries often include built-in fallback methods to make error handling much easier.
That's all!
That's pretty much it from me - I'm still learning WebSockets myself, so this may not exactly be the most detailed guide, but my hope is that it helps clear up what WebSockets do, and what they're for, for other people who got confused by them like I did.
Some other guides I found, that helped me:

Top comments (0)