在 asp.net core 中配置中間件
首先我們要在 Startup.cs 中激率,啟用 WebSocket 中間件:
varwebSocketOptions =newWebSocketOptions() {? ? KeepAliveInterval = TimeSpan.FromSeconds(120),};app.UseWebSockets(webSocketOptions);
可配置以下設置:
KeepAliveInterval - 向客戶端發(fā)送“ping”幀的頻率咳燕,以確保代理保持連接處于打開狀態(tài)。 默認值為 2 分鐘乒躺。
ReceiveBufferSize - 用于接收數(shù)據(jù)的緩沖區(qū)的大小招盲。 高級用戶可能需要對其進行更改,以便根據(jù)數(shù)據(jù)大小調(diào)整性能嘉冒。 默認值為 4 KB曹货。
AllowedOrigins - 用于 WebSocket 請求的允許的 Origin 標頭值列表。 默認情況下讳推,允許使用所有源顶籽。
接收訪客端的請求
在請求生命周期后期(例如在 Configure 方法或操作方法的后期),檢查它是否是 WebSocket 請求并接受 WebSocket 請求银觅。
app.Use(async(context, next) =>{if(context.Request.Path =="/ws")? ? {if(context.WebSockets.IsWebSocketRequest)? ? ? ? {using(WebSocket webSocket =awaitcontext.WebSockets.AcceptWebSocketAsync())? ? ? ? ? ? {awaitEcho(context, webSocket);? ? ? ? ? ? }? ? ? ? }else{? ? ? ? ? ? context.Response.StatusCode =400;? ? ? ? }? ? }else{awaitnext();? ? }});
在請求期間對 Task 執(zhí)行 await礼饱,如下面的示例所示:
app.Use(async(context, next) =>{using(WebSocket webSocket =awaitcontext.WebSockets.AcceptWebSocketAsync())? ? {varsocketFinishedTcs =newTaskCompletionSource();? ? ? ? BackgroundSocketProcessor.AddSocket(webSocket, socketFinishedTcs);awaitsocketFinishedTcs.Task;? ? }});
如果從操作方法返回過快,則還可能發(fā)生 WebSocket 關閉異常究驴。 接受操作方法中的套接字時镊绪,需要用該套接字的代碼完成運行,然后再從操作方法返回洒忧。
收發(fā)訪客端消息
AcceptWebSocketAsync 方法將 TCP 連接升級到 WebSocket 連接蝴韭,并提供 WebSocket 對象。 使用 WebSocket 對象發(fā)送和接收消息跑慕。
之前顯示的接受 WebSocket 請求的代碼將 WebSocket 對象傳遞給 Echo 方法万皿。 代碼接收消息并立即發(fā)回相同的消息摧找。 循環(huán)發(fā)送和接收消息,直到客戶端關閉連接:
privateasyncTaskEcho(HttpContext context, WebSocket webSocket){varbuffer =newbyte[1024*4];? ? WebSocketReceiveResult result =awaitwebSocket.ReceiveAsync(newArraySegment(buffer), CancellationToken.None);while(!result.CloseStatus.HasValue)? ? {awaitwebSocket.SendAsync(newArraySegment(buffer,0, result.Count), result.MessageType, result.EndOfMessage, CancellationToken.None);? ? ? ? result =awaitwebSocket.ReceiveAsync(newArraySegment(buffer), CancellationToken.None);? ? }awaitwebSocket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None);}
如果在開始循環(huán)之前接受 WebSocket 連接牢硅,中間件管道會結(jié)束蹬耘。 關閉套接字后,管道展開减余。 即接受 WebSocket 時综苔,請求停止在管道中推進。 循環(huán)結(jié)束且套接字關閉時位岔,請求繼續(xù)回到管道如筛。
處理訪客端連接斷開
訪客端由于失去連接而斷開連接時,不會自動向服務器發(fā)送通知抒抬。 服務器只有在客戶端發(fā)送通知時才會收到斷開連接消息杨刨。
如果客戶端并非總是發(fā)送消息且不希望僅由于連接進入空閑狀態(tài)就設置超時,則讓客戶端使用一個計時器并每隔多少秒發(fā)送一條心跳消息擦剑。 在服務器上妖胀,如果某條消息在上一條消息發(fā)出后的多少秒內(nèi)尚未到達,則終止連接并報告客戶端已斷開連接惠勒。