小編給大家分享一下Asp.net Core中怎么使用中間件來管理websocket,希望大家閱讀完這篇文章之后都有所收獲,下面讓我們一起去探討吧!
讓客戶滿意是我們工作的目標,不斷超越客戶的期望值來自于我們對這個行業(yè)的熱愛。我們立志把好的技術通過有效、簡單的方式提供給客戶,將通過不懈努力成為客戶在信息化領域值得信任、有價值的長期合作伙伴,公司提供的服務項目有:域名注冊、虛擬空間、營銷軟件、網站建設、和平網站維護、網站推廣。我喜歡.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
包到你的項目。
現在,您可以創(chuàng)建一個擴展方法和類來管理WebSockets:
public static class WebSocketExtensions { public static IApplicationBuilder UseCustomWebSocketManager(this IApplicationBuilder app) { return app.UseMiddleware(); } } 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 (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 (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; } }
我也創(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是您可能擁有的不同類型消息的枚舉。
在Startup類中,您必須注冊以下服務:
services.AddSingleton(); services.AddSingleton ();
CustomWebSocketFactory負責收集連接的WebSockets列表:
public interface ICustomWebSocketFactory { void Add(CustomWebSocket uws); void Remove(string username); ListAll(); List Others(CustomWebSocket client); CustomWebSocket Client(string username); } public class CustomWebSocketFactory : ICustomWebSocketFactory { List List; public CustomWebSocketFactory() { List = new List (); } public void Add(CustomWebSocket uws) { List.Add(uws); } //when disconnect public void Remove(string username) { List.Remove(Client(username)); } public List All() { return List; } public List 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包含有關消息的邏輯(即在連接時需要發(fā)送任何消息以及如何對傳入消息作出反應)
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(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 (msg); if (message.Type == WSMessageType.anyType) { await BroadcastOthers(buffer, userWebSocket, wsFactory); } } catch (Exception e) { await userWebSocket.WebSocket.SendAsync(new ArraySegment (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 (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 (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 Core中怎么使用中間件來管理websocket”有了一定的了解,如果想了解更多相關知識,歡迎關注創(chuàng)新互聯行業(yè)資訊頻道,感謝各位的閱讀!