WebSocket Fundamentals
WebSockets provide persistent, bidirectional communication between clients and servers. Unlike HTTP's request-response model, either side can send messages at any time once connected. This makes WebSockets ideal for chat, live updates, and collaborative applications.
The WebSocket Handshake
WebSocket connections start as HTTP requests, then "upgrade" to the WebSocket protocol:
Client request:
GET /chat HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Version: 13
Server response:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
The 101 Switching Protocols response confirms the upgrade. After this handshake, both sides communicate using the WebSocket protocol over the same TCP connection.
Client-Side Implementation
Browsers provide a built-in WebSocket API:
const ws = new WebSocket('wss://example.com/chat');
ws.onopen = () => {
console.log('Connected');
ws.send(JSON.stringify({
type: 'join',
room: 'general'
}));
};
ws.onmessage = (event) => {
const message = JSON.parse(event.data);
console.log('Received:', message);
};
ws.onclose = (event) => {
console.log('Disconnected:', event.code, event.reason);
};
ws.onerror = (error) => {
console.error('WebSocket error:', error);
};
Always use wss:// (WebSocket Secure) in production — it's the WebSocket equivalent of HTTPS.
Server-Side Implementation
Here's a basic Python server using FastAPI:
from fastapi import FastAPI, WebSocket
app = FastAPI()
@app.websocket("/chat")
async def websocket_endpoint(websocket: WebSocket):
await websocket.accept()
try:
while True:
data = await websocket.receive_text()
await websocket.send_text(f"Echo: {data}")
except WebSocketDisconnect:
print("Client disconnected")
The server accepts the connection, then enters a loop receiving and sending messages until the client disconnects.
Connection Lifecycle
WebSocket connections can close for many reasons — network issues, server restarts, or intentional disconnection. Robust clients implement reconnection logic:
function connect() {
const ws = new WebSocket('wss://example.com/chat');
ws.onclose = () => {
console.log('Reconnecting in 3 seconds...');
setTimeout(connect, 3000);
};
}
Consider exponential backoff for reconnection attempts to avoid overwhelming servers during outages.