在MVC控制器内打开websocket通道

Zyg*_*tas 17 c# asp.net-mvc websocket asp.net-core-mvc asp.net-core

有没有人在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);           
}
Run Code Online (Sandbox Code Playgroud)

问题:是否存在任何已知的缺点,而不是在中间件中处理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文件中配置app.UseWebSockets().否则,IsWebSocketRequest将为false.谁知道为什么?握手?

dav*_*owl 6

看起来不错。

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

我假设所有这些代码都是临时的,实际上您将从网络套接字中读取某些内容。

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

  • 使用SSL(实际托管SSL时)
  • 它不能在多台服务器上运行(这是点对点套接字连接)
  • 您需要支持处理部分帧。如果您知道客户端不会发送任何邮件,则可以将其平移。