Polydesk-logotype
Polydesk.ai — Header

WebSocket

WebSocket est un protocole de communication réseau (RFC 6455) qui établit un canal bidirectionnel persistant (full-duplex) sur une seule connexion TCP entre un client et un serveur, permettant l’échange de données en temps réel dans les deux sens sans les allers-retours du modèle requête-réponse HTTP.

L’analogie : HTTP, c’est envoyer des lettres. Vous envoyez une lettre (requête), vous attendez la réponse. À chaque échange, une nouvelle lettre. WebSocket, c’est un appel téléphonique : la ligne reste ouverte, les deux parties peuvent parler à tout moment, sans re-composer le numéro. Cette persistance et cette bidirectionnalité font de WebSocket le protocole de référence pour le chat en temps réel, les jeux multijoueurs, les éditeurs collaboratifs, les dashboards live, et le streaming de tokens LLM.

WebSocket en un coup d’œil
Catégorie
Protocole de communication temps réel
Standard
RFC 6455 (IETF, 2011), API W3C
Transport
TCP (connexion persistante full-duplex)
Handshake
Upgrade HTTP → WebSocket (code 101)
Formats
Texte (UTF-8) et binaire
Port
80 (ws://) ou 443 (wss:// chiffré)
Alternatives
SSE, polling, gRPC streaming

Comment fonctionne WebSocket

Le handshake d’ouverture

La connexion WebSocket commence par une requête HTTP standard avec un header Upgrade: websocket. Si le serveur accepte, il répond avec le code 101 Switching Protocols, et la connexion bascule du protocole HTTP au protocole WebSocket. À partir de ce moment, la connexion TCP reste ouverte et les deux parties peuvent envoyer des messages à tout moment.

# Requête client (HTTP Upgrade) GET /chat HTTP/1.1 Host: example.com Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== Sec-WebSocket-Version: 13 # Réponse serveur HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

Échange de messages

Après le handshake, la communication se fait via des frames WebSocket. Chaque frame contient un opcode (texte, binaire, ping, pong, close), une longueur de payload, et les données. L’overhead par message est de 2 à 6 octets, contre des centaines d’octets pour les headers HTTP. Cette légèreté est ce qui rend WebSocket efficace pour les communications à haute fréquence.

Les frames ping/pong servent de heartbeat : le serveur (ou le client) envoie un ping périodiquement, et l’autre côté répond avec un pong. Si aucun pong ne revient dans un délai défini, la connexion est considérée comme morte.

Fermeture de connexion

La fermeture est initiée par l’une des parties via une frame close, avec un code de fermeture (1000 = normal, 1001 = going away, 1006 = fermeture anormale). L’autre partie confirme avec sa propre frame close, puis la connexion TCP est fermée.

WebSocket vs HTTP

Aspect WebSocket HTTP classique
Modèle Bidirectionnel, persistant (full-duplex) Requête-réponse, sans état
Connexion Reste ouverte indéfiniment Fermée après chaque réponse (ou keep-alive limité)
Qui initie Les deux parties, à tout moment Toujours le client
Overhead/message 2-6 octets Centaines d’octets (headers HTTP)
Latence Très faible (pas de handshake par message) Plus élevée (handshake TCP+TLS par connexion)
État Stateful (connexion persistante) Stateless
Scaling Complexe (session affinity requise) Simple (horizontal, sans état)
Cache Pas de cache natif Cache HTTP natif (CDN, proxies)

WebSocket vs Server-Sent Events

Le choix entre WebSocket et SSE est l’une des décisions d’architecture les plus fréquentes pour le temps réel :

Critère WebSocket SSE
Direction Bidirectionnel Unidirectionnel (serveur → client)
Protocole Protocole dédié (ws://) HTTP standard (text/event-stream)
Données Texte et binaire Texte uniquement
Reconnexion Manuelle (à implémenter) Automatique (intégrée au navigateur)
Complexité Plus complexe (gestion d’état, heartbeat) Plus simple (HTTP standard)
Proxies/CDN Peut poser problème Passe à travers la plupart des proxies
Cas d’usage Chat, jeux, collaboration, trading Notifications, dashboards, streaming LLM

La règle : si le trafic va uniquement du serveur vers le client (notifications, streaming de tokens LLM, flux de prix), SSE est plus simple et suffisant. Si vous avez besoin de communication bidirectionnelle (chat, jeux, collaboration, signaux d’annulation pendant la génération LLM), WebSocket est nécessaire.

Cas d’usage

Chat et messaging. Slack, Discord, WhatsApp Web utilisent WebSocket pour la livraison instantanée des messages. Chaque utilisateur maintient une connexion WebSocket ouverte, et les messages sont pushés en temps réel.

Jeux multijoueurs. La synchronisation de l’état du jeu entre les joueurs nécessite des échanges à très faible latence dans les deux sens. WebSocket est le standard pour les jeux web temps réel.

Éditeurs collaboratifs. Google Docs, Figma, Notion utilisent WebSocket pour synchroniser les modifications entre utilisateurs en temps réel. Chaque frappe est transmise aux autres utilisateurs via la connexion persistante.

Trading et données financières. Les plateformes de trading streament les prix en temps réel via WebSocket. La latence est critique : quelques millisecondes de retard peuvent avoir un impact financier réel.

Streaming LLM bidirectionnel. Pour les applications qui nécessitent d’envoyer des signaux pendant la génération (annulation, steering, appels d’outils mid-stream), WebSocket offre la bidirectionnalité que SSE ne fournit pas. Les subscriptions GraphQL utilisent souvent WebSocket comme transport.

IoT et monitoring. Les dispositifs IoT envoient des données de télémétrie en continu, et le serveur peut envoyer des commandes en retour. WebSocket fournit le canal bidirectionnel nécessaire.

Implémentation

Client (navigateur)

const ws = new WebSocket("wss://api.example.com/ws/chat"); ws.onopen = () => { console.log("Connexion établie"); ws.send(JSON.stringify({ type: "join", room: "general" })); }; ws.onmessage = (event) => { const data = JSON.parse(event.data); console.log("Message reçu:", data); }; ws.onclose = (event) => { console.log(`Connexion fermée: code=${event.code}`); // Logique de reconnexion ici }; ws.onerror = (error) => { console.error("Erreur WebSocket:", error); };

Serveur (Python avec FastAPI)

from fastapi import FastAPI, WebSocket, WebSocketDisconnect app = FastAPI() class ConnectionManager: def __init__(self): self.active: list[WebSocket] = [] async def connect(self, ws: WebSocket): await ws.accept() self.active.append(ws) async def broadcast(self, message: str): for ws in self.active: await ws.send_text(message) manager = ConnectionManager() @app.websocket("/ws/chat") async def chat(ws: WebSocket): await manager.connect(ws) try: while True: data = await ws.receive_text() await manager.broadcast(f"Message: {data}") except WebSocketDisconnect: manager.active.remove(ws)

Scaling des WebSockets

Les WebSockets sont stateful : chaque connexion est liée à un serveur spécifique. Cela complique le scaling horizontal :

Session affinity (sticky sessions). Le load balancer doit router les messages d’un client vers le même serveur qui maintient sa connexion. C’est le minimum requis.

Pub/Sub pour la distribution. Pour broadcast un message à tous les utilisateurs connectés (qui peuvent être sur des serveurs différents), utilisez un système pub/sub (Redis Pub/Sub, Kafka, NATS) entre les serveurs. Chaque serveur publie les messages reçus et s’abonne pour distribuer les messages aux clients connectés localement.

Services managés. Pour éviter la complexité de gestion, des services comme Ably, Pusher, PubNub et AWS AppSync gèrent l’infrastructure WebSocket à grande échelle (millions de connexions concurrentes, distribution mondiale).

Reconnexion : à implémenter côté client Contrairement à SSE (qui gère la reconnexion automatiquement), WebSocket ne reconecte pas automatiquement. Votre code client doit détecter les déconnexions (onclose) et implémenter une logique de reconnexion avec backoff exponentiel. C’est une source fréquente de bugs dans les applications temps réel.

Sécurité

Utilisez wss:// (WebSocket Secure). Jamais ws:// non chiffré en production. wss:// est l’équivalent de HTTPS pour WebSocket, chiffrant le trafic via TLS.

Authentifiez au handshake. Le handshake WebSocket est une requête HTTP : utilisez des tokens (JWT, session cookie) dans les headers ou les query params pour authentifier la connexion. Une fois établie, la connexion est authentifiée pour toute sa durée.

Validez chaque message. Les messages WebSocket sont des données non fiables envoyées par un client. Validez le format, le type et le contenu de chaque message côté serveur.

Rate limitez les messages. Un client malveillant peut envoyer des milliers de messages par seconde via une connexion ouverte. Implémentez un rate limiting par connexion côté serveur.

Erreurs courantes

Utiliser WebSocket pour du unidirectionnel. Si vous n’avez besoin que de pousser des données du serveur vers le client (notifications, dashboards, streaming LLM simple), SSE est plus simple, gère la reconnexion automatiquement, et passe mieux à travers les proxies. N’utilisez WebSocket que si la bidirectionnalité est nécessaire.

Pas de reconnexion automatique. Les connexions WebSocket se coupent (réseau instable, timeout proxy, déploiement serveur). Sans reconnexion côté client, l’application cesse de fonctionner silencieusement.

Pas de heartbeat. Sans ping/pong régulier, les connexions mortes (TCP half-open) ne sont pas détectées. Les proxies intermédiaires peuvent aussi fermer les connexions inactives après un timeout (typiquement 60-120 secondes). Un heartbeat toutes les 30 secondes maintient la connexion vivante.

Messages non structurés. Envoyer du texte libre sans format structuré (JSON avec un champ type) rend le parsing et le routing des messages côté serveur impossible à maintenir. Définissez un protocole de messages dès le début.

Ignorer le scaling. « Ça marche en dev » avec un seul serveur. En production avec 10 serveurs derrière un load balancer, les messages broadcast ne sont plus distribués. Prévoyez Redis Pub/Sub ou équivalent dès le design initial.


Questions fréquentes sur WebSocket

Quelle est la différence entre WebSocket et HTTP ?

HTTP suit un modèle requête-réponse : le client envoie une requête, le serveur répond, la connexion se ferme (ou reste en keep-alive pour de futures requêtes). WebSocket établit une connexion persistante bidirectionnelle : après le handshake initial (via HTTP), les deux parties peuvent envoyer des messages à tout moment sans re-négocier de connexion. WebSocket est adapté aux communications temps réel, HTTP aux échanges ponctuels.

Quand utiliser WebSocket plutôt que Server-Sent Events ?

Utilisez WebSocket quand vous avez besoin de communication bidirectionnelle (chat, jeux, collaboration, signaux d’annulation pendant le streaming LLM). Utilisez SSE quand le flux va uniquement du serveur vers le client (notifications, dashboards, streaming de tokens LLM simple). SSE est plus simple à implémenter, gère la reconnexion automatiquement, et passe mieux à travers les proxies HTTP.

WebSocket est-il utilisé pour le streaming des LLM ?

Oui, mais SSE est plus courant pour le cas simple (serveur streame les tokens vers le client). Les API d’OpenAI et Anthropic utilisent SSE pour le streaming. WebSocket est préféré quand l’application nécessite de la bidirectionnalité pendant la génération : annulation en cours de stream, envoi d’appels d’outils, ou steering interactif. Les subscriptions GraphQL utilisent WebSocket comme transport.

Comment gérer des milliers de connexions WebSocket ?

Les serveurs modernes (Node.js, Go, Python async avec uvicorn) peuvent gérer des dizaines de milliers de connexions WebSocket par instance. Le goulot d’étranglement est rarement le nombre de connexions, mais le broadcast (envoyer un message à N clients). Pour scaler : utilisez Redis Pub/Sub ou NATS pour distribuer les messages entre serveurs, configurez des sticky sessions au load balancer, et monitorez la mémoire par connexion. Les services managés (Ably, Pusher) gèrent des millions de connexions.

WebSocket fonctionne-t-il derrière un CDN ou un proxy ?

La plupart des CDN et proxies modernes supportent WebSocket (Cloudflare, AWS ALB, NGINX). Cependant, certains proxies d’entreprise ou firewalls peuvent bloquer les connexions WebSocket. Le timeout par défaut des proxies (60-120 secondes d’inactivité) peut fermer les connexions silencieusement. Solution : un heartbeat (ping/pong) toutes les 30 secondes maintient la connexion active à travers les proxies.

Polydesk.ai — Footer