WebSocket est un protocole de communication qui ouvre un canal bidirectionnel persistant entre client et serveur sur une seule connexion TCP. Contrairement à HTTP (requête → réponse), les deux parties peuvent envoyer des données à tout moment.
WebSocket démarre par une requête HTTP (upgrade), puis bascule sur son propre protocole. Voir Requêtes HTTP et HTTPS pour le contexte HTTP.
Le problème que WebSocket résout
HTTP classique (requête/réponse) :
Client ──► GET /messages ← le client doit demander
Client ◄── 200 [données]
... 5 secondes plus tard ...
Client ──► GET /messages ← polling : inefficace
Client ◄── 200 [rien de nouveau]
WebSocket (canal persistant) :
Client ──► Handshake HTTP → upgrade WebSocket
════ Canal TCP persistant ouvert ════════════════
Serveur ──► {"event": "new_message", "text": "Salut"} ← push immédiat
Client ──► {"event": "typing", "user": "Alice"} ← push immédiat
Serveur ──► {"event": "new_message", "text": "..."}
Handshake — ouverture de la connexion
La connexion WebSocket commence par une requête HTTP spéciale :
1. Requête HTTP du client (Upgrade) :
GET /ws HTTP/1.1
Host: api.exemple.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13
2. Réponse du serveur (101 Switching Protocols) :
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
3. La connexion TCP reste ouverte → plus de HTTP, protocole WS
Le code
101 Switching Protocolsest la réponse HTTP qui “upgrade” la connexion.
Cycle de vie d’une connexion WebSocket
Client Serveur
│── HTTP Upgrade ────────────────► │
│◄── 101 Switching Protocols ──── │
│ │
│════ Canal WebSocket ouvert ═════ │
│ │
│── Message {"type": "join"} ────► │
│◄── Message {"type": "welcome"} ─ │
│◄── Message {"type": "push"} ──── │ (push serveur)
│── Message {"type": "ping"} ────► │ (keepalive)
│◄── Message {"type": "pong"} ──── │
│ │
│── Close frame ─────────────────► │ (fermeture propre)
│◄── Close frame ───────────────── │
│════ Connexion TCP fermée ════════ │
Exemples de code
// Côté client (JavaScript navigateur)
const ws = new WebSocket('wss://api.exemple.com/ws'); // wss = WebSocket + TLS
ws.onopen = () => {
console.log('Connexion ouverte');
ws.send(JSON.stringify({ type: 'subscribe', channel: 'notifications' }));
};
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
console.log('Message reçu:', data);
};
ws.onclose = (event) => {
console.log('Connexion fermée:', event.code, event.reason);
// Reconnexion automatique si nécessaire
setTimeout(() => reconnect(), 3000);
};
ws.onerror = (error) => {
console.error('Erreur WebSocket:', error);
};
// Envoyer un message
ws.send(JSON.stringify({ type: 'message', text: 'Bonjour' }));
// Fermer proprement
ws.close(1000, 'Session terminée');# Côté serveur (Python / websockets)
import asyncio
import websockets
import json
connected_clients = set()
async def handler(websocket):
connected_clients.add(websocket)
try:
async for message in websocket:
data = json.loads(message)
if data["type"] == "message":
# Diffuser à tous les clients connectés
for client in connected_clients:
if client != websocket:
await client.send(json.dumps({
"type": "message",
"text": data["text"],
"from": data.get("user")
}))
finally:
connected_clients.remove(websocket)
async def main():
async with websockets.serve(handler, "0.0.0.0", 8765):
await asyncio.Future() # run forever
asyncio.run(main())Protocoles au-dessus de WebSocket
WebSocket transporte des bytes bruts. Des protocoles applicatifs sont souvent ajoutés par-dessus :
| Protocole | Usage | Description |
|---|---|---|
| STOMP | Messaging | Simple Text Oriented Messaging Protocol — canaux, abonnements |
| MQTT over WS | IoT | Protocole léger pour appareils contraints |
| Socket.IO | Web temps réel | Bibliothèque avec fallback HTTP polling et reconnexion automatique |
| GraphQL Subscriptions | APIs GraphQL | Requêtes GraphQL en push via WebSocket |
// Socket.IO — abstraction populaire au-dessus de WebSocket
const io = require('socket.io')(server);
io.on('connection', (socket) => {
socket.on('join_room', (room) => {
socket.join(room);
});
socket.on('message', (data) => {
// Envoyer à tous dans la même room
io.to(data.room).emit('message', data);
});
});Codes de fermeture WebSocket
| Code | Signification |
|---|---|
1000 | Fermeture normale |
1001 | Endpoint parti (navigateur fermé, serveur restart) |
1006 | Fermeture anormale (pas de Close frame reçu) |
1008 | Message violant la politique du serveur |
1011 | Erreur interne serveur |
WebSocket vs alternatives temps réel
| Technologie | Direction | Connexion | Cas d’usage | Support |
|---|---|---|---|---|
| WebSocket | Bidirectionnel | Persistante | Chat, jeux, collaboration | Excellent |
| SSE (Server-Sent Events) | Serveur → Client | Persistante (HTTP) | Notifications push, live feed | Bon (HTTP natif) |
| HTTP Long Polling | Serveur → Client | Répétées | Fallback legacy | Universel |
| HTTP Short Polling | Client interroge | Répétées | Simple mais inefficace | Universel |
SSE (Server-Sent Events) — alternative légère pour du push unidirectionnel :
GET /events
Accept: text/event-stream
data: {"type": "notification", "message": "Nouveau message"}
data: {"type": "update", "count": 42}
WebSocket dans Kubernetes / microservices
# Ingress NGINX — activer WebSocket (nécessite les bons headers)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
nginx.ingress.kubernetes.io/configuration-snippet: |
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
spec:
rules:
- host: ws.exemple.com
http:
paths:
- path: /ws
backend:
service:
name: websocket-service
port:
number: 8765Les load balancers L4 (TCP) passent WebSocket nativement. Les load balancers L7 doivent explicitement gérer les headers
UpgradeetConnection.
En relation avec
- API — Vue d’ensemble — comparatif des types d’API
- API GraphQL — GraphQL Subscriptions reposent sur WebSocket
- Requêtes HTTP et HTTPS — WebSocket commence par un handshake HTTP
- Paquets IP et TCP — WebSocket repose sur une connexion TCP persistante