首页 > 网络编程 > ASP.NET > 正文

Asp.net Core中如何使用中间件来管理websocket_实用技巧

2018-10-12 16:22:04

介绍

我喜欢.NET CORE 这个东西,其实不仅仅源于它性能很高,可以跨平台,还因为它的设计模式确实令人着迷。以前没.NET CORE 的时候,.NET用websocket必须跑在windows server 2012上,但我一般不会这么干,都把websocket架在nodejs的服务器上。这么分出来,麻烦肯定是麻烦的,而且js这东西,写复杂和几年后再看都是头疼的问题。那么,如果.NET CORE是以kestrel运行的,那么就不再需要考虑服务器的版本运行,任何一个地方都可以用websocket

ASP.NET Core SignalR是一个有用的库,可以简化Web应用程序中实时通信的管理。但是,我宁愿使用WebSockets,因为我想要更灵活,并且与任何WebSocket客户端兼容。

在Microsoft的文档中,我找到了一个很好的WebSockets工作示例。它仍然是管理连接,以便能够从一个连接向其他连接广播消息,这是SignalR开箱即用的功能。期望这个逻辑非常复杂,我想从Startup类中删除它。

背景

要阅读ASP.NET Core中的WebSockets支持,可以在此处查看。如果您想了解中间件以及如何在ASP.NET Core中编写它,请阅读此链接

代码使用

首先,你必须添加 Microsoft.AspNetCore.WebSockets 包到你的项目。

现在,您可以创建一个扩展方法和类来管理WebSockets:

public static class WebSocketExtensions{ public static IApplicationBuilder UseCustomWebSocketManager(this IApplicationBuilder app) {  return app.UseMiddleware<CustomWebSocketManager>(); }}public class CustomWebSocketManager{ private readonly RequestDelegate _next; public CustomWebSocketManager(RequestDelegate next) {  _next = next; } public async Task Invoke(HttpContext context, ICustomWebSocketFactory wsFactory, ICustomWebSocketMessageHandler wsmHandler) {  if (context.Request.Path == "/ws")  {   if (context.WebSockets.IsWebSocketRequest)   {    string username = context.Request.Query["u"];    if (!string.IsNullOrEmpty(username))    {     WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync();     CustomWebSocket userWebSocket = new CustomWebSocket()     {      WebSocket = webSocket,      Username = username     };     wsFactory.Add(userWebSocket);     await wsmHandler.SendInitialMessages(userWebSocket);     await Listen(context, userWebSocket, wsFactory, wsmHandler);    }   }   else   {     context.Response.StatusCode = 400;   }  }  await _next(context); } private async Task Listen(HttpContext context, CustomWebSocket userWebSocket, ICustomWebSocketFactory wsFactory, ICustomWebSocketMessageHandler wsmHandler) {  WebSocket webSocket = userWebSocket.WebSocket;  var buffer = new byte[1024 * 4];  WebSocketReceiveResult result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);  while (!result.CloseStatus.HasValue)  {    await wsmHandler.HandleMessage(result, buffer, userWebSocket, wsFactory);    buffer = new byte[1024 * 4];    result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);  }   wsFactory.Remove(userWebSocket.Username);  await webSocket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None); }}

在这种情况下,WebSockets请求在URL中始终包含“/ ws”。查询字符串包含用于将WebSocket与登录用户相关联的用户名的参数u。

CustomWebSocket是一个包含WebSocket和用户名的类:

public class CustomWebSocket{ public WebSocket WebSocket { get; set; } public string Username { get; set; }}

我也创建了自定义WebSocket消息:

class CustomWebSocketMessage{ public string Text { get; set; } public DateTime MessagDateTime { get; set; } public string Username { get; set; } public WSMessageType Type { get; set; }}

其中Type是您可能拥有的不同类型消息的枚举。

在Startup类中,您必须注册以下服务:

services.AddSingleton<ICustomWebSocketFactory, CustomWebSocketFactory>();services.AddSingleton<ICustomWebSocketMessageHandler, CustomWebSocketMessageHandler>();

CustomWebSocketFactory负责收集连接的WebSockets列表:

public interface ICustomWebSocketFactory{ void Add(CustomWebSocket uws); void Remove(string username); List<CustomWebSocket> All(); List<CustomWebSocket> Others(CustomWebSocket client); CustomWebSocket Client(string username);}public class CustomWebSocketFactory : ICustomWebSocketFactory{ List<CustomWebSocket> List; public CustomWebSocketFactory() {  List = new List<CustomWebSocket>(); } public void Add(CustomWebSocket uws) {  List.Add(uws); } //when disconnect public void Remove(string username)  {  List.Remove(Client(username)); } public List<CustomWebSocket> All() {  return List; }  public List<CustomWebSocket> Others(CustomWebSocket client) {  return List.Where(c => c.Username != client.Username).ToList(); }  public CustomWebSocket Client(string username) {  return List.First(c=>c.Username == username); }}

CustomWebSocketMessageHandler包含有关消息的逻辑(即在连接时需要发送任何消息以及如何对传入消息作出反应)

public interface ICustomWebSocketMessageHandler{ Task SendInitialMessages(CustomWebSocket userWebSocket); Task HandleMessage(WebSocketReceiveResult result, byte[] buffer, CustomWebSocket userWebSocket, ICustomWebSocketFactory wsFactory); Task BroadcastOthers(byte[] buffer, CustomWebSocket userWebSocket, ICustomWebSocketFactory wsFactory); Task BroadcastAll(byte[] buffer, CustomWebSocket userWebSocket, ICustomWebSocketFactory wsFactory);}public class CustomWebSocketMessageHandler : ICustomWebSocketMessageHandler{ public async Task SendInitialMessages(CustomWebSocket userWebSocket) {  WebSocket webSocket = userWebSocket.WebSocket;  var msg = new CustomWebSocketMessage  {   MessagDateTime = DateTime.Now,   Type = WSMessageType.anyType,   Text = anyText,   Username = "system"  };  string serialisedMessage = JsonConvert.SerializeObject(msg);  byte[] bytes = Encoding.ASCII.GetBytes(serialisedMessage);  await webSocket.SendAsync(new ArraySegment<byte>(bytes, 0, bytes.Length), WebSocketMessageType.Text, true, CancellationToken.None); } public async Task HandleMessage(WebSocketReceiveResult result, byte[] buffer, CustomWebSocket userWebSocket, ICustomWebSocketFactory wsFactory) {  string msg = Encoding.ASCII.GetString(buffer);  try  {   var message = JsonConvert.DeserializeObject<CustomWebSocketMessage>(msg);   if (message.Type == WSMessageType.anyType)   {   await BroadcastOthers(buffer, userWebSocket, wsFactory);   }  }  catch (Exception e)  {   await userWebSocket.WebSocket.SendAsync(new ArraySegment<byte>(buffer, 0, result.Count), result.MessageType, result.EndOfMessage, CancellationToken.None);  } } public async Task BroadcastOthers(byte[] buffer, CustomWebSocket userWebSocket, ICustomWebSocketFactory wsFactory) {  var others = wsFactory.Others(userWebSocket);  foreach (var uws in others)  {   await uws.WebSocket.SendAsync(new ArraySegment<byte>(buffer, 0, buffer.Length), WebSocketMessageType.Text, true, CancellationToken.None);  } } public async Task BroadcastAll(byte[] buffer, CustomWebSocket userWebSocket, ICustomWebSocketFactory wsFactory) {  var all = wsFactory.All();  foreach (var uws in all)  {   await uws.WebSocket.SendAsync(new ArraySegment<byte>(buffer, 0, buffer.Length), WebSocketMessageType.Text, true, CancellationToken.None);  } }}

最后,在Configure方法的Startup类中添加以下内容:

var webSocketOptions = new WebSocketOptions(){ KeepAliveInterval = TimeSpan.FromSeconds(120), ReceiveBufferSize = 4 * 1024};app.UseWebSockets(webSocketOptions);app.UseCustomWebSocketManager();

通过这种方式,Starup类保持干净,管理WebSockets的逻辑可以扩展,使您可以根据自己的喜好灵活地组织它。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对脚本之家的支持。

  • 相关标签:ASP.NET
  • 本文发布HTML5中文学习网 ,转载请注明出处,感谢您!
  • 相关文章


  • 曝网友假装外国人写投诉信 ofo秒退押金并回函致歉
  • 苹果市值缩水逾2000亿美元 遭多家投行下调目标价
  • Asp.net Core与类库读取配置文件信息的方法_实用技巧
  • asp.net在Repeater嵌套的Repeater中使用复选框详解_实用技巧
  • 利用IIS调试ASP.NET网站程序的完整步骤_实用技巧
  • Asp.Net Core轻松学习系列之配置文件_实用技巧
  • ASP.NET 页生命周期概述(小结)_实用技巧
  • 详解ASP.NET Core WebApi 返回统一格式参数_实用技巧
  • 2018年网络流行语有哪些?2018年十大网络流行语盘点
  • 华为首席财务官孟晚舟被暂扣 深圳市政府要求加方立即放人!
  • 独孤九贱(4)_PHP视频教程

    江湖传言:PHP是世界上最好的编程语言。真的是这样吗?这个梗究竟是从哪来的?学会本课程,你就会明白了。 PHP中文网出品的PHP入门系统教学视频,完全从初学者的角度出发,绝不玩虚的,一切以实用、有用...

    独孤九贱(5)_ThinkPHP5视频教程

    ThinkPHP是国内最流行的中文PHP开发框架,也是您Web项目的最佳选择。《php.cn独孤九贱(5)-ThinkPHP5视频教程》课程以ThinkPHP5最新版本为例,从最基本的框架常识开始,将...

    独孤九贱(1)_HTML5视频教程

    《php.cn原创html5视频教程》课程特色:php中文网原创幽默段子系列课程,以恶搞,段子为主题风格的php视频教程!轻松的教学风格,简短的教学模式,让同学们在不知不觉中,学会了HTML知识。 ...

    ThinkPHP5实战之[教学管理系统]

    本套教程,以一个真实的学校教学管理系统为案例,手把手教会您如何在一张白纸上,从零开始,一步一步的用ThinkPHP5框架快速开发出一个商业项目。

    PHP入门视频教程之一周学会PHP

    所有计算机语言的学习都要从基础开始,《PHP入门视频教程之一周学会PHP》不仅是PHP的基础部分更主要的是PHP语言的核心技术,是学习PHP必须掌握的内容,任何PHP项目的实现都离不开这部分的内容,通...

    作者信息

    kevin

    永远在学习的路上!

    相关教程

  • javascript初级视频教程 javascript初级视频教程
  • jquery 基础视频教程 jquery 基础视频教程
  • javascript三级联动视频教程 javascript三级联动视频教程
  • 独孤九贱(3)_JavaScript视频教程 独孤九贱(3)_JavaScript视频教程
  • 独孤九贱(6)_jQuery视频教程 独孤九贱(6)_jQuery视频教程
  • 热门教程