有没有人有在 MVC Controller 中打开 websocket 连接的良好经验?
技术栈:ASPNET Core 1.0 (RC1) MVC、dnx46、System.Net.WebSockets
为什么选择 MVC 而不是中间件:为了整体一致性、路由、已经注入(inject)的存储库、在同一 Controller 中调用私有(private)方法的选项。
[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) 存在时(为简单起见,上面的示例中没有显示,比方说,当一个 channel 需要关闭),方法需要返回一些东西(任务)。它应该是什么? HTTP 200 状态响应?我想不会,因为在 WebSockets 文档中写道,在“关闭”帧之后不应发送任何内容。
更新 3: 我通过艰难的方式学到了一件事,如果你想在 Windows 10 上使用 IIS Express 10.0 在 Visual Studio 2015 中调试时让 WebSockets 工作,你仍然必须使用 https://github.com/aspnet/WebSockets 和在 Startup.cs 文件中配置 app.UseWebSockets()。否则,IsWebSocketRequest 将为假。任何人都知道为什么?握手?
最佳答案
看起来不错。
- 您可能想将
while(true)
更改为while (!HttpContext.RequestAborted.IsCancellationRequested)
以便检测客户端断开连接并结束请求。 - 您无需在调用 accept 后检查 null 或 websocket 的状态。
我假设所有这些代码都是临时的,您实际上会从 websocket 中读取一些东西。
所有常用的 websocket 规则都适用:
- 使用 SSL(当您真正托管它时)
- 它不能在多个服务器上工作(它是点对点套接字连接)
- 您需要支持处理部分帧。如果您知道客户不会发送任何信息,您可以下注。
关于c# - 在 MVC Controller 中打开一个 websocket channel ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35554128/