WebSockets: The Open Phone Line
Like having an always-open phone line rather than sending letters back and forth, WebSockets maintain a persistent, bidirectional channel between client and server. Either side can send messages at any time - no request needed, no waiting.
Key Insight: The Open Phone Line
WebSockets establish a single connection and keep it open indefinitely. Both client and server can send messages at any time without waiting for requests. The tiny 2-14 byte frame overhead (vs ~1KB HTTP headers) makes it ideal for high-frequency real-time applications like chat, gaming, and live data feeds.
Key Concepts
- Persistent Connection: One-time handshake, then channel stays open indefinitely
- Full Duplex: Both client AND server can send messages at any time
- Minimal Overhead: 2-14 bytes per frame vs ~1KB HTTP headers
- Server Push: Server can initiate communication without client request
The key insight: one connection handles unlimited messages in both directions, with near-zero overhead per message.
How It Works
The Handshake
WebSocket connections start with an HTTP upgrade request:
GET /socket HTTP/1.1 Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade
Connection Lifecycle
Client Server | | |--- HTTP Upgrade Request ----->| |<-- 101 Switching Protocols ---| | | |========= WS Connection ========| | | |<------- Message Frame -------->| (bidirectional) |<------- Message Frame -------->| | | |--- Close Frame (1000) -------->| |<-- Close Frame (1000) ---------|
Implementation
import websocket def on_message(ws, message): print(f"Received: {message}") def on_open(ws): ws.send("Hello, Server!") ws = websocket.WebSocketApp( "wss://example.com/socket", on_message=on_message, on_open=on_open ) ws.run_forever()
Performance Characteristics
Overhead Comparison
For 1,000 messages:
- HTTP Polling: 1,000 × 1KB = 1MB overhead
- WebSocket: 1,000 × 6B = 6KB overhead
- Improvement: 170× less overhead
Latency
| Aspect | HTTP Polling | WebSocket |
|---|---|---|
| Message Latency | 0-interval | ~0ms |
| Connection Setup | Every request | Once |
| Bidirectional | No | Yes |
Trade-offs
Advantages
- True bidirectional communication
- Minimal per-message overhead
- Server can push without request
- Single persistent connection
Limitations
- Requires WebSocket support (most proxies now support it)
- More complex than HTTP
- Connection state to manage
- Memory per connection (~10-50KB)
When to Use
Perfect For
- Real-time collaboration - Google Docs, Figma
- Live updates - Stock tickers, sports scores
- Gaming - Multiplayer games, game state sync
- Chat applications - Instant messaging
Not Ideal For
- Simple request-response - REST APIs, form submissions
- Cacheable content - Static resources
- Infrequent updates - Weather apps
Related Concepts
- Short Polling - The simple but wasteful approach
- Long Polling - HTTP-based near real-time
- Client-Server Communication - Compare all approaches side-by-side
- Linux Networking Stack - How TCP connections are handled at the kernel level
