在 ASP.NET Core 中使用 WebSocket 实时更新商品信息,通常分为两部分:

  1. 服务端:通过 WebSocket 建立连接并推送消息
  2. 客户端:接收 WebSocket 消息并更新 UI(如商品价格/库存变动)

🔹 一、服务端实现 WebSocket

在 Program.cs 或 Startup.cs 中启用 WebSocket:

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

// 启用 WebSockets
var webSocketOptions = new WebSocketOptions
{
    KeepAliveInterval = TimeSpan.FromSeconds(120),
    AllowedOrigins = { "http://localhost:5000" } // 允许的前端来源
};
app.UseWebSockets(webSocketOptions);

// 处理 WebSocket 请求
app.Map("/ws", async context =>
{
    if (context.WebSockets.IsWebSocketRequest)
    {
        using var webSocket = await context.WebSockets.AcceptWebSocketAsync();
        Console.WriteLine("WebSocket 已连接");

        var buffer = new byte[1024 * 4];
        while (true)
        {
            var result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
            if (result.MessageType == WebSocketMessageType.Close)
            {
                await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "关闭连接", CancellationToken.None);
                break;
            }
            else
            {
                // 处理客户端发来的消息
                var clientMsg = Encoding.UTF8.GetString(buffer, 0, result.Count);
                Console.WriteLine($"客户端消息: {clientMsg}");
            }
        }
    }
    else
    {
        context.Response.StatusCode = 400;
    }
});

app.Run();

🔹 二、模拟商品信息实时推送

可以通过一个后台任务,定期更新商品价格并推送给所有 WebSocket 客户端。

public class WebSocketHandler
{
    private readonly List<WebSocket> _sockets = new();

    public async Task HandleAsync(HttpContext context)
    {
        var webSocket = await context.WebSockets.AcceptWebSocketAsync();
        _sockets.Add(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)
            {
                _sockets.Remove(webSocket);
                await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "关闭连接", CancellationToken.None);
            }
        }
    }

    // 广播商品信息
    public async Task BroadcastProductUpdate(string productJson)
    {
        var msg = Encoding.UTF8.GetBytes(productJson);
        foreach (var socket in _sockets.ToList())
        {
            if (socket.State == WebSocketState.Open)
            {
                await socket.SendAsync(new ArraySegment<byte>(msg), WebSocketMessageType.Text, true, CancellationToken.None);
            }
        }
    }
}

注册并在 Program.cs 使用:

var handler = new WebSocketHandler();

app.Map("/ws", async context => await handler.HandleAsync(context));

// 模拟后台商品更新
_ = Task.Run(async () =>
{
    var rnd = new Random();
    while (true)
    {
        var product = new
        {
            Id = 1,
            Name = "iPhone 16 Pro",
            Price = rnd.Next(6000, 9000),
            Stock = rnd.Next(10, 100)
        };
        string json = JsonSerializer.Serialize(product);
        await handler.BroadcastProductUpdate(json);

        await Task.Delay(5000); // 每5秒推送一次
    }
});

🔹 三、前端客户端接收更新

在前端(JS / React / Vue)中建立 WebSocket 连接:

const socket = new WebSocket("ws://localhost:5000/ws");

socket.onopen = () => {
  console.log("WebSocket 已连接");
};

socket.onmessage = (event) => {
  const product = JSON.parse(event.data);
  console.log("商品更新:", product);

  document.getElementById("product").innerText =
    `商品:${product.Name} | 价格:${product.Price} | 库存:${product.Stock}`;
};

✅ 最终效果:

  • 服务端定时推送商品信息(价格、库存)。
  • 客户端实时接收并更新页面内容。