Introduction : Pourquoi WebSocket est-il la norme pour les applications temps réel ?
Les applications web modernes nécessitent une réaction instantanée aux actions de l'utilisateur. Qu'il s'agisse d'un chat en ligne, d'un terminal boursier, d'un jeu multijoueur ou d'un système de surveillance — les retards dans la transmission des données sont inacceptables. Le protocole HTTP traditionnel, fonctionnant sur le principe "requête-réponse", est inefficace pour ces scénarios : le client doit interroger constamment le serveur (polling), créant une charge excessive.
Le WebSocket vient à la rescousse — un protocole assurant une connexion bidirectionnelle permanente entre le client et le serveur. Dans cet article, nous allons voir comment créer des applications temps réel en C# (.NET) en utilisant WebSocket, d'un simple serveur écho à un chat complet. Vous apprendrez comment fonctionne le protocole, quels outils la plateforme .NET propose, et comment éviter les erreurs courantes.
Fondamentaux de WebSocket dans .NET : Partie serveur
La plateforme .NET offre un support intégré pour WebSocket via l'espace de noms System.Net.WebSockets. Examinons la création d'un serveur basé sur ASP.NET Core.
1. Configuration du Middleware pour WebSocket
Pour commencer, il faut ajouter le support WebSocket au pipeline de traitement des requêtes. Dans le fichier Program.cs :
var builder = WebApplication.CreateBuilder(args);var app = builder.Build();
app.UseWebSockets(); // Activation du support WebSocket
app.Map("/ws", async (HttpContext context) =>{ if (context.WebSockets.IsWebSocketRequest) { using var webSocket = await context.WebSockets.AcceptWebSocketAsync(); await Echo(webSocket); } else { context.Response.StatusCode = 400; }});
app.Run("http://localhost:5000");
async Task Echo(WebSocket webSocket){ var buffer = new byte[1024 * 4]; var receiveResult = await webSocket.ReceiveAsync( new ArraySegment<byte>(buffer), CancellationToken.None);
while (!receiveResult.CloseStatus.HasValue) { // Renvoi des données reçues au client (écho) await webSocket.SendAsync( new ArraySegment<byte>(buffer, 0, receiveResult.Count), receiveResult.MessageType, receiveResult.EndOfMessage, CancellationToken.None);
receiveResult = await webSocket.ReceiveAsync( new ArraySegment<byte>(buffer), CancellationToken.None); }
await webSocket.CloseAsync( receiveResult.CloseStatus.Value, receiveResult.CloseStatusDescription, CancellationToken.None);}Ce code crée un serveur écho : tout ce que le client envoie lui est renvoyé. Notez l'utilisation de async/await — le travail avec WebSocket est toujours asynchrone.
2. Gestion de plusieurs connexions
Dans une application réelle, il faut gérer de multiples connexions. Créons un gestionnaire de connexions simple :
public class WebSocketConnectionManager{ private readonly ConcurrentDictionary<string, WebSocket> _connections = new();
public string AddConnection(WebSocket socket) { var id = Guid.NewGuid().ToString(); _connections.TryAdd(id, socket); return id; }
public async Task BroadcastMessageAsync(string message) { var tasks = _connections.Values.Select(async socket => { if (socket.State == WebSocketState.Open) { var bytes = Encoding.UTF8.GetBytes(message); await socket.SendAsync( new ArraySegment<byte>(bytes), WebSocketMessageType.Text, true, CancellationToken.None); } }); await Task.WhenAll(tasks); }}Cette classe permet de stocker toutes les connexions actives et de diffuser des messages