在 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。有人知道为什么吗?握手?
似乎没问题。
- 您可能希望将
while(true)
更改为while (!HttpContext.RequestAborted.IsCancellationRequested)
,以便检测客户端断开连接并结束请求。
调用 - accept 后,无需检查 null 或 websocket 的状态。
我假设所有这些代码都是临时的,你实际上会从 websocket 中读取一些东西。
所有常用的 websocket 规则都适用:
- 使用 SSL(当您真正托管它时)
- 它不适用于多个服务器(它是点对点套接字连接)
- 您需要支持处理部分帧。如果您知道客户端不会发送任何内容,则可以对此进行投注。