WebSocket en C#: creación de aplicaciones en tiempo real con .NET

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course
```html

Introducción a WebSocket en C# para aplicaciones en tiempo real

Las aplicaciones web modernas requieren cada vez más una transmisión instantánea de datos entre el cliente y el servidor. El protocolo HTTP tradicional, que funciona bajo el esquema de "solicitud-respuesta", no es eficiente para tareas donde son importantes una baja latencia y una actualización constante de la información: chats en línea, cotizaciones bursátiles, juegos multijugador, sistemas de monitoreo. Aquí es donde entra en juego WebSocket, un protocolo que proporciona una conexión bidireccional permanente.

En el ecosistema de C# (.NET), la implementación de WebSocket está disponible tanto a través de las clases integradas del espacio de nombres System.Net.WebSockets como a través de la biblioteca de alto nivel SignalR. En este artículo, analizaremos ambos enfoques, escribiremos ejemplos funcionales y discutiremos las características arquitectónicas de las aplicaciones en tiempo real. El material será útil tanto para desarrolladores .NET principiantes como para los experimentados.

Fundamentos de WebSocket: cómo funciona en C#

WebSocket es un protocolo que, después del handshake HTTP inicial (solicitud de actualización), transforma la conexión en un modo bidireccional permanente. En C#, el trabajo con WebSocket se basa en la programación asíncrona utilizando las palabras clave async y await.

Creación de un servidor WebSocket simple en C#

Consideremos un ejemplo básico de un servidor que acepta conexiones WebSocket y responde al cliente con eco. Para ello, utilizaremos la clase integrada HttpListener o Kestrel (ASP.NET Core). A continuación se muestra un ejemplo basado en ASP.NET Core.

// Startup.cs o Program.cs (API mínima)
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.UseWebSockets();

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;
    }
});

async Task Echo(WebSocket webSocket)
{
    var buffer = new byte[1024 * 4];
    while (webSocket.State == WebSocketState.Open)
    {
        var result = await webSocket.ReceiveAsync(
            new ArraySegment<byte>(buffer), CancellationToken.None);
        if (result.MessageType == WebSocketMessageType.Close)
        {
            await webSocket.CloseAsync(
                WebSocketCloseStatus.NormalClosure, "Closing", CancellationToken.None);
        }
        else
        {
            // Enviamos los datos de vuelta (eco)
            await webSocket.SendAsync(
                new ArraySegment<byte>(buffer, 0, result.Count),
                result.MessageType,
                result.EndOfMessage,
                CancellationToken.None);
        }
    }
}

app.Run();

El código demuestra la mecánica básica: AcceptWebSocketAsync transforma la solicitud HTTP en WebSocket, y los métodos ReceiveAsync y SendAsync proporcionan el intercambio de datos asíncrono. Es importante manejar el estado de la conexión y cerrarla correctamente.

Cliente WebSocket en C#

La parte del cliente también es simple. Usamos la clase ClientWebSocket:

using System.Net.WebSockets;

async Task ConnectAndSend()
{
    using var client = new ClientWebSocket();
    await client.ConnectAsync(new Uri("ws://localhost:5000/ws"), CancellationToken.None);

    var message = "¡Hola, WebSocket!";
    var bytes = Encoding.UTF8.GetBytes(message);
    await client.SendAsync(new ArraySegment<byte>(bytes),
        WebSocketMessageType.Text, true, CancellationToken.None);

    var buffer = new byte[1024];
    var result = await client.ReceiveAsync(
        new ArraySegment<byte>(buffer), CancellationToken.None);
    var response = Encoding.UTF8.GetString(buffer, 0, result.Count);
    Console.WriteLine($"Respuesta del servidor: {response}");
}
```

Blogs

Book Recommendations