ASP.NET 核心 WebSocket

Yuc*_*ked 10 c# websocket .net-core asp.net-core

我正在尝试在 ASP.NET Core 上启动并运行 WebSocket 服务器。我创建了一个空的 web 项目,dotnet new web将其更改Program.cs为:

public static void Main(string[] args) {
    Host.CreateDefaultBuilder(args)
    .ConfigureWebHostDefaults(webBuilder => {
        webBuilder.UseStartup<Startup>();
    })
    .Build()
    .Run();
}
Run Code Online (Sandbox Code Playgroud)

AndStartup.csConfigureServices方法:

public void ConfigureServices(IServiceCollection services) {
    services.AddControllers();
    services.AddWebSockets();
}
Run Code Online (Sandbox Code Playgroud)

Configure方法:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
    app.UseWebSockets();
    app.UseRouting();
    app.UseEndpoints(endpoints => {
        endpoints.MapControllers();
        endpoints.MapConnectionHandler<WebSocketHandler>("/ws");
    });
}
Run Code Online (Sandbox Code Playgroud)

WebSocketHandlerOnConnectedAsync方法如下:

public override async Task OnConnectedAsync(ConnectionContext connection) 
{
    var context = connection.GetHttpContext();
    var endpoint = $"{connection.RemoteEndPoint}";

    if (!context.WebSockets.IsWebSocketRequest) {
        connection.Abort();
        _logger.LogCritical($"Request from {endpoint} endpoint aborted.");
        return;
    }

    var websocket = await context.WebSockets.AcceptWebSocketAsync();
    _logger.LogInformation($"WebSocket request from {endpoint} endpoint accepted!");
}
Run Code Online (Sandbox Code Playgroud)

当我尝试连接时出现问题,APP_URL/ws并且每次服务器在收到请求后立即关闭连接。以下是日志:https : //pastebin.com/raw/34yu7thw

如果我将 aTask.Delay(-1)放在OnConnectedAsync方法的末尾,它会保持连接打开但丢弃传入连接。

我搜索了 MSDocs,但没有找到太多关于如何使用MapConnectionHandler<T>.

有一个从多个客户端接收消息的 while 循环对我来说安全OnConnectedAsync吗?这不是处理 websocket 连接的正确方法吗?是MapConnectionHandler<T>短暂的吗?

我真的很困惑,无法弄清楚它的行为。

koo*_*ng3 8

我已经使用这些文档在 ASP.NET 核心中实现了一个 WebSocket 服务器,它对我来说效果很好:https : //docs.microsoft.com/en-us/aspnet/core/fundamentals/websockets?view=aspnetcore- 3.1

主要思想是,在您接受请求后,AcceptWebSocketAsync()您将获得返回的WebSocket对象并使用它来发送和接收。通常,您会创建一个循环,调用ReceiveAsync直到满足某个条件(当您收到特定消息或客户端断开连接等时,您确定会话已完成)。正如文档所述,When using a WebSocket, you must keep the middleware pipeline running for the duration of the connection.因此,如果您将该WebSocket连接传递给后台工作人员以执行发送/接收,则需要在与该客户端的交互期间保持该管道打开。然后,当您完成后,您会向中间件发出信号,表明连接已完成并且可以展开。

我怀疑不保持连接打开和循环是你的问题。我以前没有使用MapConnectionHandler过 WebSockets,所以这可能行不通,但上述策略可能对您有所帮助,或者按照这样的后台工作者的文档进行操作:

app.Use(async (context, next) => {
    var socket = await context.WebSockets.AcceptWebSocketAsync();
    var socketFinishedTcs = new TaskCompletionSource<object>();

    BackgroundSocketProcessor.AddSocket(socket, socketFinishedTcs); 

    await socketFinishedTcs.Task;
});
Run Code Online (Sandbox Code Playgroud)

  • 我发现BackgroundSocketProcessor 未定义?我缺少任何图书馆吗? (3认同)