Les WebSockets sont un protocole de communication qui permet une communication en temps réel entre le client et le serveur. Les WebSockets maintiennent la connexion vivante et permettent une communication bidirectionnelle. Les WebSockets conviennent donc aux applications de chat et de bourse, aux jeux multijoueurs et aux outils de collaboration.
Dans cet article, nous allons explorer le fonctionnement du protocole WebSocket et les avantages de son utilisation par rapport au protocole HTTP. Nous vous montrerons également comment créer une application de chat simple en utilisant les WebSockets dans le frontend et le backend.
Le protocole HTTP est largement utilisé pour les interactions entre le serveur et le client. Il fonctionne bien pour récupérer des données et créer des ressources. Mais il est unidirectionnel, ce qui signifie que le client doit initier toutes les requêtes et que le serveur ne peut pas envoyer de données de son propre chef. Cette limitation le rend inefficace pour des applications telles que les téléscripteurs boursiers ou les jeux multijoueurs, où il est nécessaire de transférer des mises à jour entre le client et le serveur des centaines ou des milliers de fois par minute. Pour chaque mise à jour, le client doit répéter un cycle demande réponse, ce qui consomme beaucoup de ressources informatiques et de bande passante. L'utilisation du protocole HTTP pour de telles applications rend également le serveur inefficace, car il est surchargé de nouvelles demandes, même lorsqu'aucune mise à jour n'est disponible pour les clients.
Pour remédier à cette limitation, vous pouvez essayer le HTTP long polling, dans lequel le serveur maintient la connexion ouverte plus longtemps en attendant d'envoyer plus de données avec la réponse. Dès que le client reçoit la réponse, il émet une nouvelle requête pour demander plus de données. Bien que cela fonctionne bien pour reproduire le comportement en temps réel, le fait de maintenir une connexion ouverte pendant une longue période peut entraîner des problèmes de dépassement de délai du serveur et nuire aux performances si un trop grand nombre de clients continuent d'interroger le serveur même lorsque de nouvelles mises à jour ne sont pas disponibles. En outre, comme le client effectue des requêtes à des intervalles prédéfinis, les mises à jour peuvent ne pas apparaître instantanément. Imaginons, par exemple, un jeu vidéo multijoueur qui doit synchroniser les positions et les scores des joueurs en temps réel. Le protocole HTTP devrait envoyer une nouvelle requête toutes les quelques secondes pour récupérer le dernier état du jeu, ce qui ajoute une surcharge et une latence inutiles au réseau.
En revanche, les WebSockets permettent de réduire considérablement la latence et les frais généraux du réseau tout en conservant un canal bidirectionnel pour la communication en temps réel. L'utilisation d'une connexion full-duplex permet au client et au serveur d'interagir et d'envoyer des messages sans créer de nouvelle connexion, ce qui réduit la surcharge de transmission liée à la création d'une nouvelle connexion pour chaque requête. La connexion persistante dans les WebSockets minimise l'utilisation de la bande passante en n'envoyant pas les en-têtes HTTP avec chaque message. Les WebSockets offrent également une sensation de temps réel aux applications car elles n'ont pas besoin de suivre un cycle d'interrogation. Ainsi, les nouvelles données arrivent instantanément dès qu'elles sont disponibles. Tous ces avantages font des WebSockets une option beaucoup plus pratique pour les utilisations en temps réel, telles que les applications de chat et de bourse, les jeux multijoueurs et les outils de collaboration.
Voici un diagramme comparant la chronologie des connexions HTTP et WebSockets :
Si vous avez déjà créé une fonction de chat utilisant l'interrogation HTTP, vous connaissez la douleur : les utilisateurs se plaignent des messages retardés, les serveurs gémissent sous les demandes constantes, et ce sentiment d'impuissance lorsque vous réalisez que votre application "en temps réel" a un retard de 5 secondes. Les sockets Web résolvent élégamment ce problème en maintenant une connexion bidirectionnelle persistante qui donne l'impression d'être vraiment instantanée.
Le protocole WebSocket crée une connexion persistante entre le client et le serveur pour une communication bidirectionnelle. Le processus de connexion commence par une requête HTTP appelée "handshake", au cours de laquelle le client demande au serveur de faire évoluer la connexion vers le protocole WebSocket. Après la poignée de main, la connexion passe au protocole WebSocket. Le diagramme suivant montre la séquence de connexion entre le client et le serveur.
Voici comment fonctionne la connexion au protocole WebSocket : Le client envoie une requête HTTP au serveur pour une mise à niveau de la connexion vers le protocole WebSocket. La requête comprend les en-têtes Upgrade : websocket
et Connection :
Upgrade
, comme dans l'exemple suivant :
GET /chat HTTP/1.1
Host: example.com:8000
Upgrade: websocket
Connection: Upgrade
Le serveur envoie une réponse au client avec un code d'état 101
pour indiquer que la connexion a été mise à niveau vers le protocole WebSocket. La réponse comprend les en-têtes Upgrade : websocket
et Connection : Upgrade
. Voici un exemple :
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Après la poignée de main, le client et le serveur peuvent maintenant communiquer de manière bidirectionnelle sans aucune demande supplémentaire.
Le client ou le serveur peut fermer la connexion à tout moment.
Nous allons maintenant vous montrer comment créer une application de chat simple à l'aide de WebSockets, qui vous permet d'envoyer et de recevoir des messages. L'application frontend permettra aux utilisateurs d'envoyer des messages, et le serveur backend diffusera les messages à tous les clients connectés.
Vous pouvez suivre le processus en utilisant ce dépôt GitHub.
Pour commencer, créez un dossier de projet nommé websockets-js-node
dans votre répertoire de travail en exécutant mkdir websockets-js-node
dans votre outil de ligne de commande.
Dans le dossier du projet, créez un répertoire nommé frontend
en exécutant mkdir frontend
dans votre outil de ligne de commande.
Dans le répertoire frontend
, créez un fichier nommé index.html
en exécutant touch index.html
dans votre outil de ligne de commande.
Dans le fichier index.html
, ajoutez le code pour rendre une page HTML simple avec des champs de saisie pour le nom d'utilisateur et le message, un bouton pour envoyer le message, et une balise de script
pour inclure le fichier de script index.js
qui implémente la logique WebSocket du frontend, comme suit :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>WebSocket Client</title>
</head>
<body>
<h1>WebSocket Client</h1>
<input type="text" id="username" placeholder="Your username" />
<input type="text" id="messageInput" placeholder="Type your message" />
<button onclick="sendMessage()">Send</button>
<div id="messages"></div>
<script src="index.js"></script>
</body>
</html>
Créez un fichier nommé index.js
en exécutant touch index.js
dans votre outil de ligne de commande, et ajoutez le code suivant pour configurer la connexion WebSocket au serveur backend :
// frontend/script.js
// Créer une connexion WebSocket au serveur
const socket = new WebSocket("ws://localhost:8080");
// Afficher l'état de la connexion
socket.onopen = () => {
console.log("Connecté au serveur WebSocket");
};
// Gérer les messages entrants du serveur
socket.onmessage = (event) => {
const messageDiv = document.getElementById("messages");
const newMessage = document.createElement("p");
newMessage.textContent = event.data.toString();
messageDiv.appendChild(newMessage);
};
// Gérer la fermeture de la connexion
socket.onclose = () => {
console.log("Déconnecté du serveur WebSocket");
};
// Envoyer un message au serveur
function sendMessage() {
const usernameInput = document.getElementById("username");
const messageInput = document.getElementById("messageInput");
const message = messageInput.value;
const username = usernameInput.value;
if (message) {
socket.send(`${username}: ${message}`);
messageInput.value = "";
}
}
Le code effectue les opérations suivantes :
socket.onopen
est déclenché lorsque la connexion est établie.socket.onmessage
est déclenché lorsqu'un message est reçu du serveur. Il ajoute le message à la div messages
.socket.onclose
est déclenché lorsque la connexion est fermée.sendMessage
est appelée lorsque l'utilisateur clique sur le bouton Envoyer. Elle récupère le nom d'utilisateur et le message dans les champs de saisie et les envoie au serveur à l'aide de la méthode socket.send.
Maintenant que le frontend est prêt, créons un serveur backend auquel le frontend peut se connecter pour envoyer et recevoir des messages. Dans la section suivante, nous expliquons comment mettre en œuvre une application de chat simple qui diffuse les messages entrants à tous les clients connectés.
Pour l'implémentation du backend, cet exemple utilise le package npm ws, qui est une bibliothèque éprouvée pour créer un serveur WebSocket dans Node.js.
Notez que les exemples de code de ce tutoriel sont réalisés avec la version 20 de Node.js.
Dans le dossier du projet, créez un nouveau répertoire nommé backend
en exécutant mkdir backend
dans votre outil de ligne de commande. Dans le répertoire backend
, créez un fichier nommé server.js
en exécutant touch server.js
dans votre outil de ligne de commande.
Exécutez la commande suivante dans votre outil de ligne de commande pour installer le paquetage ws
:
npm install ws
Dans le fichier server.js
, ajoutez le code suivant pour créer un serveur HTTP simple et un serveur WebSocket utilisant le serveur HTTP :
// backend/server.js
const http = require("http");
const { WebSocketServer } = require("ws");
// Créer un simple serveur HTTP
const server = http.createServer((req, res) => {
res.writeHead(200, { "Content-Type": "text/plain" });
res.end("Le serveur WebSocket est en cours d'exécution.\n");
});
// Créer un serveur WebSocket à l'aide du serveur HTTP
const wss = new WebSocketServer({ server });
wss.on("connection", (ws) => {
console.log("Nouveau client connecté");
// Envoyer un message de bienvenue au nouveau client connecté
ws.send("Server: Bienvenue sur le serveur WebSocket !");
// Écouter les messages du client
ws.on("message", (message) => {
// Diffuser le message reçu à tous les clients connectés
wss.clients.forEach((client) => {
if (client.readyState === ws.OPEN) {
client.send(message.toString());
}
});
});
// Gérer la déconnexion du client
ws.on("close", () => {
console.log("Client déconnecté");
});
});
// Démarrer le serveur HTTP et WebSocket sur le port 8080
server.listen(8080, () => {
console.log("Le serveur est en cours d'exécution sur http://localhost:8080");
});
Le code du serveur effectue les opérations suivantes :
on("connection")
est déclenché lorsqu'un nouveau client se connecte au serveur WebSocket. Le serveur envoie un message de bienvenue au client nouvellement connecté et commence à écouter les messages du client.on("message")
est déclenché lorsqu'un message est reçu d'un client et qu'il est diffusé à tous les clients connectés.on("close")
est déclenché lorsqu'un client se déconnecte du serveur WebSocket.server.listen()
est utilisée pour démarrer le serveur HTTP et WebSocket sur le port 8080.Pour lancer le serveur, naviguez jusqu'au répertoire backend
et exécutez node server.js
dans votre outil de ligne de commande. Cela démarrera le serveur et le rendra accessible à l'application frontend à l'adresse http://localhost:8080.
Ouvrez le fichier frontend/index.html
dans deux onglets du navigateur web pour tester l'application de chat en temps réel. Remplissez les noms d'utilisateur et envoyez des messages à partir d'un onglet, et ils apparaîtront dans l'autre onglet en temps réel.
Le résultat final devrait ressembler à ceci :
Considérations relatives à la production
Si notre exemple fonctionne parfaitement pour le développement, les applications WebSocket de production nécessitent des considérations supplémentaires telles que la gestion des connexions, l'authentification et la gestion des interruptions du réseau. Les plateformes modernes comme Upsun gèrent automatiquement un grand nombre de ces aspects, y compris l'équilibrage des connexions WebSocket et la gestion de la fin du protocole SSL.
La création d'une application WebSocket n'est qu'un début ; c'est en la faisant fonctionner de manière fiable en production que les choses deviennent intéressantes. Vous devez gérer la mise à l'échelle lorsque votre application de chat devient virale, déboguer les problèmes de performance dans les connexions en temps réel et tester de nouvelles fonctionnalités sans interrompre l'expérience en direct de vos utilisateurs.
C'est là qu'Upsun brille. En tant que plateforme centrée sur les développeurs et conçue pour les applications modernes, Upsun rend le déploiement d'applications WebSocket très simple. Chaque poussée Git crée automatiquement un environnement de prévisualisation complet, y compris votre serveur WebSocket, votre base de données et toutes les dépendances, de sorte que vous pouvez tester des fonctionnalités en temps réel avec des données réelles avant qu'elles ne soient mises en production.
De plus, grâce à l'observabilité et à la surveillance des performances intégrées, vous pouvez repérer les goulots d'étranglement de connexion ou les problèmes de livraison de messages avant que vos utilisateurs ne le fassent. Que vous construisiez une simple application de chat ou un outil de collaboration en temps réel complexe, Upsun gère la complexité de l'infrastructure afin que vous puissiez vous concentrer sur ce qui rend votre application spéciale.
Prêt à voir à quel point le déploiement de WebSocket peut être facile ? Commencez votre essai gratuit et votre application en temps réel fonctionnera en quelques minutes.