欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Asp.net Core中如何使用中間件來(lái)管理websocket

 更新時(shí)間:2018年09月07日 09:08:52   作者:nopapp  
這篇文章主要給大家介紹了關(guān)于Asp.net Core中如何使用中間件來(lái)管理websocket的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

介紹

我喜歡.NET CORE 這個(gè)東西,其實(shí)不僅僅源于它性能很高,可以跨平臺(tái),還因?yàn)樗脑O(shè)計(jì)模式確實(shí)令人著迷。以前沒(méi).NET CORE 的時(shí)候,.NET用websocket必須跑在windows server 2012上,但我一般不會(huì)這么干,都把websocket架在nodejs的服務(wù)器上。這么分出來(lái),麻煩肯定是麻煩的,而且js這東西,寫(xiě)復(fù)雜和幾年后再看都是頭疼的問(wèn)題。那么,如果.NET CORE是以kestrel運(yùn)行的,那么就不再需要考慮服務(wù)器的版本運(yùn)行,任何一個(gè)地方都可以用websocket

ASP.NET Core SignalR是一個(gè)有用的庫(kù),可以簡(jiǎn)化Web應(yīng)用程序中實(shí)時(shí)通信的管理。但是,我寧愿使用WebSockets,因?yàn)槲蚁胍`活,并且與任何WebSocket客戶端兼容。

在Microsoft的文檔中,我找到了一個(gè)很好的WebSockets工作示例。它仍然是管理連接,以便能夠從一個(gè)連接向其他連接廣播消息,這是SignalR開(kāi)箱即用的功能。期望這個(gè)邏輯非常復(fù)雜,我想從Startup類(lèi)中刪除它。

背景

要閱讀ASP.NET Core中的WebSockets支持,可以在此處查看。如果您想了解中間件以及如何在ASP.NET Core中編寫(xiě)它,請(qǐng)閱讀此鏈接

代碼使用

首先,你必須添加 Microsoft.AspNetCore.WebSockets 包到你的項(xiàng)目。

現(xiàn)在,您可以創(chuàng)建一個(gè)擴(kuò)展方法和類(lèi)來(lái)管理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請(qǐng)求在URL中始終包含“/ ws”。查詢字符串包含用于將WebSocket與登錄用戶相關(guān)聯(lián)的用戶名的參數(shù)u。

CustomWebSocket是一個(gè)包含WebSocket和用戶名的類(lèi):

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

我也創(chuàng)建了自定義WebSocket消息:

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

其中Type是您可能擁有的不同類(lèi)型消息的枚舉。

在Startup類(lèi)中,您必須注冊(cè)以下服務(wù):

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

CustomWebSocketFactory負(fù)責(zé)收集連接的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包含有關(guān)消息的邏輯(即在連接時(shí)需要發(fā)送任何消息以及如何對(duì)傳入消息作出反應(yīng))

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類(lèi)中添加以下內(nèi)容:

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

app.UseWebSockets(webSocketOptions);
app.UseCustomWebSocketManager();

通過(guò)這種方式,Starup類(lèi)保持干凈,管理WebSockets的邏輯可以擴(kuò)展,使您可以根據(jù)自己的喜好靈活地組織它。

總結(jié)

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。

相關(guān)文章

最新評(píng)論