
Mise en place d'un serveur WebSocket avec le module ws ou Socket.IO
Apprenez a implementer un serveur WebSocket en Node.js en utilisant les bibliotheques populaires ws et Socket.IO. Guide pas a pas et exemples concrets.
Choisir sa bibliothèque : `ws` ou `Socket.IO` ?
Maintenant que nous comprenons les principes des WebSockets, il est temps de passer à l'implémentation côté serveur avec Node.js. Plutôt que de réimplémenter tout le protocole WebSocket manuellement, nous utilisons des bibliothèques qui simplifient grandement le processus. Deux options principales dominent l'écosystème Node.js :
- `ws` : Une bibliothèque populaire, très performante et de bas niveau. Elle fournit une implémentation proche du standard WebSocket, vous donnant un contrôle fin sur le protocole mais moins de fonctionnalités "prêtes à l'emploi" pour des cas d'usage applicatifs courants. C'est un excellent choix si vous avez besoin d'une implémentation WebSocket pure et légère, ou si vous construisez votre propre couche d'abstraction par-dessus.
- `Socket.IO` : Une bibliothèque beaucoup plus complète et de plus haut niveau. Bien qu'elle utilise les WebSockets comme transport principal lorsque c'est possible, `Socket.IO` n'est pas une simple implémentation WebSocket. Elle ajoute une couche d'abstraction significative avec des fonctionnalités telles que les mécanismes de repli (fallbacks) vers d'autres transports (comme le long-polling HTTP) si les WebSockets ne sont pas disponibles, la reconnexion automatique, la détection de déconnexion (heartbeat), la diffusion vers des groupes (rooms), les namespaces, et un système d'événements personnalisés plus riche. C'est souvent le choix privilégié pour développer des applications temps réel complexes en raison de sa robustesse et de ses fonctionnalités intégrées. Notez que `Socket.IO` nécessite une bibliothèque cliente correspondante côté navigateur (ou autre client).
Nous allons voir comment mettre en place un serveur simple avec les deux options.
Option 1 : Utilisation du module `ws` (Bas niveau)
1. Installation : Ajoutez `ws` à vos dépendances de projet.
npm install ws
# ou
yarn add ws2. Création du serveur WebSocket : Vous pouvez soit attacher un serveur WebSocket à un serveur HTTP/S Node.js existant (courant si vous servez aussi une application web), soit créer un serveur WebSocket autonome.
const WebSocket = require('ws');
// --- Option A: Serveur WebSocket autonome ---
const wss = new WebSocket.Server({ port: 8080 });
console.log('Serveur WebSocket (ws) écoute sur le port 8080');
// --- Option B: Attaché à un serveur HTTP existant ---
/*
const http = require('http');
const server = http.createServer((req, res) => {
// Logique de votre serveur HTTP classique ici...
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Serveur HTTP actif.\n');
});
const wssAttached = new WebSocket.Server({ server }); // Attache au serveur HTTP
console.log('Serveur WebSocket (ws) attaché au serveur HTTP');
server.listen(8081, () => {
console.log('Serveur HTTP écoute sur le port 8081');
});
*/
// 3. Gestion des connexions
wss.on('connection', (wsClient) => {
// wsClient représente la connexion avec un client spécifique
console.log('Client WebSocket connecté !');
// Envoyer un message au client dès la connexion
wsClient.send('Bienvenue sur le serveur WebSocket (ws) !');
// 4. Gestion des messages reçus du client
wsClient.on('message', (message) => {
// Le message est souvent un Buffer, convertissez-le si nécessaire
const messageText = message.toString();
console.log('Message reçu du client:', messageText);
// Exemple : Renvoyer le message reçu à l'expéditeur (echo)
// wsClient.send(`Vous avez dit : ${messageText}`);
// Exemple : Diffuser le message à tous les clients connectés (Broadcasting)
wss.clients.forEach((client) => {
// Vérifie si le client est différent de l'expéditeur et est prêt
if (client !== wsClient && client.readyState === WebSocket.OPEN) {
client.send(`Nouveau message de quelqu'un d'autre : ${messageText}`);
}
});
});
// 5. Gestion de la fermeture de connexion
wsClient.on('close', () => {
console.log('Client WebSocket déconnecté.');
});
// 6. Gestion des erreurs de connexion
wsClient.on('error', (error) => {
console.error('Erreur WebSocket client:', error);
});
});
// Gestion des erreurs du serveur lui-même
wss.on('error', (error) => {
console.error('Erreur Serveur WebSocket:', error);
});Avec `ws`, vous travaillez directement avec les événements `connection`, `message`, `close`, `error` et la méthode `send()`. Pour des fonctionnalités comme les rooms ou la diffusion ciblée, vous devez implémenter la logique vous-même (par exemple, en maintenant un tableau ou un Set des clients connectés).
Option 2 : Utilisation de `Socket.IO` (Haut niveau)
1. Installation :
npm install socket.io
# ou
yarn add socket.io2. Création du serveur Socket.IO : `Socket.IO` s'intègre généralement à un serveur HTTP/S existant.
const http = require('http');
const { Server } = require("socket.io"); // Importe la classe Server
const server = http.createServer((req, res) => {
// Servir le fichier HTML/JS client si nécessaire
// (Exemple très basique, utiliser Express pour une vraie app)
if (req.url === '/') {
res.writeHead(200, { 'Content-Type': 'text/html' });
// Assurez-vous d'avoir un fichier index.html qui inclut le client Socket.IO
res.end('Serveur Socket.IO
');
} else {
res.writeHead(404);
res.end();
}
});
// Crée une instance de serveur Socket.IO attachée au serveur HTTP
const io = new Server(server, {
// options éventuelles (cors, etc.)
});
console.log('Serveur Socket.IO prêt.');
// 3. Gestion des connexions
io.on('connection', (socket) => {
// socket représente la connexion avec un client spécifique
console.log(`Un utilisateur s'est connecté : ${socket.id}`);
// Envoyer un message au client qui vient de se connecter
socket.emit('bienvenue', 'Bienvenue sur le serveur Socket.IO !');
// Envoyer un message à tous les autres clients pour les notifier
socket.broadcast.emit('nouvel utilisateur', `L'utilisateur ${socket.id} a rejoint.`);
// 4. Ecouter des événements personnalisés envoyés par le client
socket.on('chat message', (msg, callback) => {
console.log(`Message de ${socket.id} : ${msg}`);
// Diffuser le message à tous les clients, y compris l'expéditeur
io.emit('chat message', { id: socket.id, message: msg });
// Utilisation d'un accusé de réception (acknowledgement)
if (callback) {
callback({ status: "ok", timestamp: Date.now() });
}
});
// Exemple avec les "rooms"
socket.on('join room', (roomName) => {
socket.join(roomName);
console.log(`${socket.id} a rejoint la room ${roomName}`);
// Envoyer un message uniquement aux membres de la room
io.to(roomName).emit('room message', `Bienvenue dans ${roomName}, ${socket.id}!`);
});
// 5. Gestion de la déconnexion
socket.on('disconnect', (reason) => {
console.log(`Utilisateur ${socket.id} déconnecté. Raison: ${reason}`);
// Notifier les autres utilisateurs
io.emit('utilisateur parti', `L'utilisateur ${socket.id} est parti.`);
});
// Gestion des erreurs spécifiques au socket
socket.on('error', (error) => {
console.error('Erreur Socket.IO client:', error);
});
});
server.listen(8082, () => {
console.log('Serveur HTTP avec Socket.IO écoute sur http://localhost:8082');
});Avec `Socket.IO`, la communication est basée sur des événements nommés personnalisés (`emit`, `on`) plutôt que sur un simple événement `message`. Il fournit des méthodes directes pour la diffusion (`io.emit`, `socket.broadcast.emit`), la gestion des salles (`socket.join`, `socket.leave`, `io.to(roomName).emit`), et bien plus encore, rendant le développement d'applications complexes plus rapide.
Considérations finales
Le choix entre `ws` et `Socket.IO` dépend de vos besoins spécifiques. Si vous avez besoin d'une implémentation WebSocket pure, légère et contrôlée, `ws` est un excellent choix. Si vous développez une application web temps réel et que vous bénéficiez des fonctionnalités avancées (rooms, fallbacks, reconnexion, API événementielle riche), `Socket.IO` vous fera probablement gagner beaucoup de temps et d'efforts, malgré sa couche d'abstraction supplémentaire et la nécessité d'utiliser sa bibliothèque côté client.
Dans les deux cas, la mise en place d'un serveur WebSocket ou utilisant des WebSockets avec Node.js est relativement simple grâce à ces bibliothèques, ouvrant la porte à la création d'expériences utilisateur dynamiques et interactives.