DEV Community

dsmith_sys
dsmith_sys

Posted on

Brief About How the Protocol Switch Happens in WebSocket

Understanding What Actually Happens During a WebSocket Connection

If you've ever used WebSocket through libraries like ws or Socket.IO, you probably know that it enables real-time communication. But have you ever wondered what actually happens under the hood when a WebSocket connection is established?

Most explanations jump straight to APIs, but I wanted to understand how the protocol switch actually happens.

Before diving into the internals, let's first understand the problem WebSocket was trying to solve.

The Problem with HTTP

HTTP follows a request-response model.

A client sends a request, the server processes it, and then sends back a response. After that, the conversation is over unless the client sends another request.

That works perfectly for applications like loading web pages or fetching data. However, it becomes inefficient for real-time applications such as:

  • Chat applications
  • Multiplayer games
  • Live notifications
  • Stock or cryptocurrency price updates
  • Collaborative editors like Google Docs

In these applications, the server should also be able to send data whenever something changes instead of waiting for the client to ask every time.

WebSocket solves this problem by reusing the existing TCP connection.

Instead of creating a completely new transport protocol, it first performs a one-time HTTP Upgrade Handshake. Once both the client and the server agree, they stop communicating using HTTP rules and start communicating using WebSocket rules—all over the same TCP connection.

Now that we know why WebSocket exists, let's understand how this protocol switch actually happens.


Let's Understand TCP

TCP (Transmission Control Protocol) was introduced by Vint Cerf and Bob Kahn as part of the TCP/IP protocol suite.

It follows a three-way handshake to establish a reliable connection between the client and the server.

TCP is a transport-layer protocol. It does not know the meaning of the data it is transporting.

The data is transported in an ordered manner using sequence numbers, which help TCP reconstruct the byte stream correctly at the receiving end.

It ensures reliable delivery. If any data is lost or corrupted during transmission, TCP retransmits it.

To TCP, everything is simply a stream of bytes.

Whether those bytes represent HTTP, WebSocket, JSON, an image, or anything else is none of TCP's concern.


How HTTP Is Built on Top of TCP

Here, the TCP connection is not changing in any way.

We simply interpret the byte stream using HTTP's text-based rules.

When the client sends data following the HTTP format (such as GET, headers, CRLF, etc.), the server in its HTTP state starts the HTTP parser and parses the incoming bytes as an HTTP request.

If the incoming bytes do not follow HTTP's formatting rules, the HTTP parser treats the request as invalid and usually returns an error or closes the connection.


Finally... How Does the Protocol Switch Happen?

So far, we know:

  • TCP is simply the transporter (or the road).
  • Different protocols can run on top of the same TCP connection.

That means HTTP and WebSocket are simply different sets of rules for interpreting the same byte stream.

What Are the WebSocket Rules?

The WebSocket protocol consists of two parts:

  1. HTTP Upgrade Handshake (used only once to switch the protocol)
  2. Binary Framing (used for all communication after the protocol switch)

Similarly, HTTP has its own rules like:

  • GET
  • Headers
  • Status codes
  • CRLF formatting

Now let's understand the first part.


HTTP Upgrade Handshake

The HTTP Upgrade Handshake is the moment where both the client and server agree to stop speaking HTTP and start speaking WebSocket.

In simple terms:

They stop parsing incoming bytes using HTTP rules and start parsing them using WebSocket rules.

Internally, you can imagine something like:

let currentState = "http";

// After successful handshake
currentState = "websocket";
Enter fullscreen mode Exit fullscreen mode

This isn't the actual implementation, but it provides the correct mental model.

Step 1 — Browser Sends an Upgrade Request

The browser sends a normal HTTP GET request containing headers like:

GET /chat HTTP/1.1
Host: example.com
Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13
Enter fullscreen mode Exit fullscreen mode

Important headers:

  • Connection: Upgrade
  • Upgrade: websocket
  • Sec-WebSocket-Key (used for handshake verification)

Step 2 — Server Verifies the Request

The server parses the request as a completely normal HTTP request.

When it sees the upgrade request, it:

  1. Appends a fixed WebSocket magic GUID to the received Sec-WebSocket-Key.
  2. Hashes the result using SHA-1.
  3. Base64 encodes the hash.
  4. Places the result inside the Sec-WebSocket-Accept header.
  5. Sends back a 101 Switching Protocols response.

Example:

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Enter fullscreen mode Exit fullscreen mode

The browser performs the exact same calculation independently.

If both values match:

  • The handshake succeeds.
  • Both browser and server switch from HTTP mode to WebSocket mode.

If they don't match, the connection is rejected.


Binary Framing

Once the protocol has been switched, the browser no longer sends HTTP requests over that connection.

Instead, every message follows the WebSocket frame format.

This is simply another set of rules for interpreting the byte stream.

A WebSocket parser reads each frame in a predefined structure:

  • FIN bit → Is this the final fragment?
  • Opcode → Text, binary, ping, pong, close, etc.
  • Mask bit → Whether the payload is masked.
  • Payload Length → How many bytes belong to the payload.

After reading this metadata, the parser extracts the payload correctly.

Because every message now follows this frame structure, the server no longer tries to interpret the bytes as an HTTP request.

The TCP connection never changes.

Only the parser sitting on top of TCP changes.


Visualizing the Switch

                TCP Connection
────────────────────────────────────────────

Client                         Server

HTTP Request  ───────────────►  HTTP Parser

GET
Connection: Upgrade
Upgrade: websocket

                Handshake

HTTP 101 Switching Protocols ◄──────────────

        Protocol Switch Happens

WebSocket Frames ─────────────► WebSocket Parser

Frame
Frame
Frame
Frame

Still the SAME TCP connection.
Only the protocol rules changed.
Enter fullscreen mode Exit fullscreen mode

Why Didn't WebSocket Create a Brand-New Protocol?

Now that we understand how the protocol switch happens, the next obvious question is:

Why did WebSocket choose to upgrade HTTP instead of creating an entirely new protocol?

This was one question that kept bothering me.

If WebSocket has its own framing protocol, why not just create a completely new protocol from day one?

A few reasons came to mind.

1. Easier Implementation (Partially)

My first thought was:

"Probably because it's easier."

And that's partially true.

Instead of inventing a brand-new protocol and convincing everyone to support it, WebSocket simply borrows HTTP for a few moments and then says:

"Thanks, I'll take it from here."

2. HTTP Was Already the King 👑

This is the real reason.

By the time WebSocket was introduced, HTTP was everywhere.

  • Browsers understood it.
  • Servers understood it.
  • Reverse proxies understood it.
  • Firewalls understood it.
  • Load balancers understood it.

Basically, the entire internet had already agreed:

"Yep... we all speak HTTP."

Imagine if WebSocket had suddenly appeared and said:

"Hey everyone! I've invented a brand-new protocol. Please update your browsers, proxies, firewalls, servers, and every piece of networking infrastructure on Earth."

Yeah... good luck with that.

Instead, WebSocket made the smartest move possible.

It started as a completely normal HTTP request, passed through all the existing infrastructure without raising any eyebrows, and only after both sides agreed did it quietly switch to its own protocol.

  • No new TCP connection.
  • No special ports.
  • No reinventing the web.

Just one HTTP handshake and then...

"Alright HTTP, you've done your job. I'll handle the rest."


In One Sentence

WebSocket didn't replace HTTP—it used HTTP's popularity to get through the front door, and once both the client and server agreed, it switched to its own binary framing protocol while continuing to use the same TCP connection.

Top comments (1)

Collapse
 
frank_signorini profile image
Frank

How does the HTTP upgrade request handle errors during the protocol switch, and have you seen any issues with this in production - would love to hear your thoughts on this.