在 MVC 控制器中打开一个 websocket 通道

本文关键字:一个 websocket 通道 控制器 MVC | 更新日期: 2023-09-27 18:35:38

有没有人在MVC控制器中打开websocket连接?

技术堆栈:ASPNET Core 1.0 (RC1) MVC、dnx46、System.Net.WebSockets

为什么选择MVC而不是中间件:为了整体一致性,路由,已经注入的存储库,在同一控制器中调用私有方法的选项。

[HttpGet("v1/resources/{id}")]
public async Task<IActionResult> GetAsync(string id)
{
    var resource = await this.repository.GetAsync(id);
    if (resource == null)
    {
        return new HttpStatusCodeResult(404);
    }
    if (this.HttpContext.WebSockets.IsWebSocketRequest)
    {
        var webSocket = await this.HttpContext.WebSockets.AcceptWebSocketAsync();
        if (webSocket != null && webSocket.State == WebSocketState.Open)
        {
            while (true)
            {
                var response = string.Format("Hello! Time {0}", System.DateTime.Now.ToString());
                var bytes = System.Text.Encoding.UTF8.GetBytes(response);
                await webSocket.SendAsync(new System.ArraySegment<byte>(bytes),
                    WebSocketMessageType.Text, true, CancellationToken.None);
                await Task.Delay(2000);
            }
        }
    }
    return new HttpStatusCodeResult(101);           
}

问题:除了在中间件中处理 websocket 连接之外,是否有任何已知的缺点?握手怎么样,除了返回HTTP 101状态代码之外,我们还需要做其他事情吗?

更新 1:为什么不是 SignalR? 没有必要使用回退技术,因此虽然它是一个不错的产品,但在这种情况下添加额外的依赖项没有任何好处。

更新 2:我已经注意到的一个缺点 - 当 while(true) 存在时(出于简单原因,上面的例子中没有显示,比如说,当需要关闭通道时),方法需要返回一些东西(任务)。应该是什么?HTTP 200 状态响应?我想不会,因为在 WebSockets 文档中编写了"关闭"帧后不应发送任何内容。

更新3:我学到的一件事是,如果你想在Windows 10上使用IIS Express 10.0在Visual Studio 2015中进行调试时让WebSockets工作,你仍然必须使用 https://github.com/aspnet/WebSockets 和配置应用程序。在 Startup.cs 文件中使用WebSockets()。否则,IsWebSocketRequest 将为 false。有人知道为什么吗?握手?

在 MVC 控制器中打开一个 websocket 通道

似乎没问题。

  • 您可能希望将while(true)更改为while (!HttpContext.RequestAborted.IsCancellationRequested),以便检测客户端断开连接并结束请求。
  • 调用
  • accept 后,无需检查 null 或 websocket 的状态。

我假设所有这些代码都是临时的,你实际上会从 websocket 中读取一些东西。

所有常用的 websocket 规则都适用:

  • 使用 SSL(当您真正托管它时)
  • 它不适用于多个服务器(它是点对点套接字连接)
  • 您需要支持处理部分帧。如果您知道客户端不会发送任何内容,则可以对此进行投注。