C#C
C#3y ago
doom 🐘

❔ Websockets and Async

I am just trying to use websockets to send some events from server periodically. Once close is sent from the client, I need to stop it. But how do I process client message that only occurs once in a while.

using System.Net.WebSockets;
using System.Text;

var builder = WebApplication.CreateBuilder(args);
builder.Logging.ClearProviders();
builder.Logging.AddConsole();
var app = builder.Build();

app.UseWebSockets();

app.UseDefaultFiles();
app.UseStaticFiles();

app.Use(async (context, next) =>
{
    if (context.Request.Path == "/ws")
    {
        if (context.WebSockets.IsWebSocketRequest)
        {
            using var webSocket = await context.WebSockets.AcceptWebSocketAsync();
            await Echo(context, webSocket);
        }
        else
        {
            context.Response.StatusCode = StatusCodes.Status400BadRequest;
        }
    }
    else
    {
        await next();
    }
});

async Task Echo(HttpContext context, WebSocket webSocket)
{

    var buffer = new byte[1024 * 4];
    var receiveResult = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
    var message = Encoding.UTF8.GetBytes("Hello from server");

    Task.Run(async () =>
    {
        receiveResult = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
        app.Logger.LogInformation("Received: " + receiveResult.CloseStatusDescription);
    });

    while (!receiveResult.CloseStatus.HasValue)
    {
        await webSocket.SendAsync(new ArraySegment<byte>(message, 0, message.Length), WebSocketMessageType.Text, true, CancellationToken.None);
        await Task.Delay(1000);

        if (Encoding.UTF8.GetString(buffer).Contains("close"))
        {
            await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, receiveResult.CloseStatusDescription, CancellationToken.None);
            return;
        }
    }

    app.Logger.LogInformation("Closing connection");
};

app.Run();
Was this page helpful?