Beyond the Request-Response Model: The Need for Real-Time Communication
In the traditional HTTP model, a client sends a request and a server returns a response. In a browser, communication usually starts with a client request, so applications that need events sent by the server relied on additional mechanisms. This limitation became visible as interactive applications developed.
Chat applications, stock dashboards, multiplayer games, and collaborative document editors often need events to arrive with low delay. With HTTP/1.1, this was handled in part with techniques known as :
- Short Polling: The client repeatedly sends requests to the server at a fixed interval, for example every 2 seconds, to check whether new data has arrived. This can generate considerable network traffic when most responses are empty and introduces a delay.
- Long Polling (Comet): An improvement where the client sends a request, and the server holds the connection open until it has new data to send. Once data is sent, the connection is closed, and the client immediately opens a new one. This reduces the number of empty responses but is more complex to implement and consumes server resources.
These mechanisms increased request traffic. With long polling, the client sent another request after each response. WebSocket defines a standard channel in which both parties can send data after the session is established.
What is WebSocket? A Bidirectional Channel
The enables a two-way communication session between a client and a server. After the connection is established, both parties can send data at any time. This is .
In HTTP/1.1, one connection can carry multiple requests, but each exchange has request and response semantics. After its handshake, the classic WebSocket variant uses a long-lived TCP connection in which the client and server exchange frames without repeating HTTP headers for every message. This reduces overhead for applications with frequent data exchange.
The WebSocket Handshake: Upgrading the Connection
The WebSocket handshake is designed to work with HTTP servers and proxies. In the classic variant it starts as an HTTP/1.1 request and commonly uses port 80 or 443, although another port may be specified. This process is called the WebSocket handshake. Separate bootstrapping mechanisms are defined for HTTP/2 and HTTP/3.
How the Handshake Works
- The Client Request (HTTP Upgrade): The client (browser) initiates the handshake by sending an HTTP GET request to the server. The request includes special headers that signal the intention to switch from HTTP to WebSocket.
GET /chat HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13Key headers in this request are:
Connection: UpgradeandUpgrade: websocket: These two headers are the official signal to the server that the client wants to switch protocols.Sec-WebSocket-Key: The client sends a randomly generated, Base64-encoded value. The key does not authenticate the client. It is part of a challenge-response mechanism that checks whether the server recognized the WebSocket request.
- The Server Response (Switching Protocols): A WebSocket-aware server, upon receiving this upgrade request, will process it and send back a special HTTP response. If the server agrees to the upgrade, it will reply with a
101 Switching Protocolsstatus code.HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=Key elements of the response are:
- Status Code : This code confirms that the server is switching from HTTP to the protocol indicated by the Upgrade header.
Sec-WebSocket-Accept: The server concatenates the client'sSec-WebSocket-Keywith the fixed GUID specified by RFC 6455, computes a SHA-1 hash, and Base64-encodes the result. The client performs the same operation and compares the result with the response. The header confirms that the server accepts the connection. It is not an authentication mechanism.
After a successful handshake, the connection switches to WebSocket framing. The client and server can then send data independently. Messages are carried in one or more frames without HTTP headers for each message.
WebSocket URIs: ws and wss
Just as HTTP has its own URI scheme (http://), WebSocket defines its own schemes to identify WebSocket endpoints.
ws://(WebSocket)- This scheme identifies a WebSocket connection without TLS. Its default port is TCP 80, although another port may be specified. Network observers can read the data, so sensitive information requires transport-layer protection.
wss://(WebSocket Secure)- This scheme identifies a WebSocket connection protected by TLS and is analogous to HTTPS. Its default port is TCP 443. TLS provides confidentiality and integrity when the certificate and connection configuration are valid.
// Unencrypted WebSocket connection
ws://chat.example.com/api
// Secure, encrypted WebSocket connection
wss://realtime.example.com/stocksWebSocket Data Frames: The Conversation Protocol
After the handshake, all data is sent in units called WebSocket frames. This is a lightweight framing protocol designed to minimize overhead. Each frame starts with a small header, followed by a payload containing the application data. The header contains metadata about the payload.
- FIN bit: A flag indicating whether this is the final frame of a message. This allows messages to be fragmented into multiple frames.
- Opcode: A 4-bit field that identifies the frame type. Typical values are
0x0for continuation,0x1for text,0x2for binary data,0x8for close,0x9for ping, and0xAfor pong:continuation: A frame containing the next part of a fragmented message.text: The payload is UTF-8 text data.binary: The payload is raw binary data.close: A special control frame for closing the connection.ping/pong: Control frames used to check connection activity and detect a broken connection.
- Control frames: Close, ping, and pong frames cannot be fragmented, and their payload is at most 125 bytes. A pong response confirms receipt of a ping and can be used to check connection activity.
- Masking: All frames sent from the client to the server must be masked with a 32-bit key. The client XORs the key with the payload, which limits cache-poisoning risks at intermediary proxies. The key is included in the frame header.
- Payload length and data: The header also contains the length of the payload, followed by the payload data itself.
WebSocket framing reduces overhead compared with sending complete HTTP requests and responses. The minimum header of an unmasked frame is 2 bytes. A client frame also carries a 4-byte masking key. The length field can contain a value from 0 to 125 or indicate a following 16-bit or 64-bit length field. This is useful for frequent short messages.
WebSocket Use Cases and Applications
The bidirectional WebSocket channel is used in applications that react to server-sent events with low delay.
Chat Applications
WebSocket supports chat rooms and messaging apps. After a user sends a message, the server can forward it to other connected clients without polling for updates.
Multiplayer Online Games
Games require low-latency communication to synchronize player positions, actions, and game state. WebSocket can provide a two-way channel in an application running in the browser.
Live Financial Data Feeds
Stock tickers, cryptocurrency exchanges, and financial dashboards can receive price updates without periodic polling. A server can send new data to many connected clients.
Collaborative Editing
Applications such as Google Docs or collaborative code editors can use WebSocket to transmit changes, keystrokes, and cursor movements to session participants.
Real-Time Notifications
When an email arrives, a social media mention occurs, or a server job completes, the server can send a notification to the browser over WebSocket. The user does not need to refresh the page.
Live Sports Updates
Sports services can send score updates, commentary, and statistics during an event, complementing the content shown on a second screen.
Summary: A Protocol for Interactive Applications
The WebSocket protocol extends web communication with a persistent, full-duplex channel for interactive applications. In the classic variant it uses one TCP connection and low-overhead frames, reducing the need for periodic client polling.
The HTTP-based handshake supports interoperability with existing servers and intermediaries. After it completes, the server can send events without a separate request for every message, while the client can still initiate its own messages.