.NetCore WebSocket簡單實現
阿新 • • 發佈:2019-02-10
專案需要使用.net core的webapi後臺處理一個大檔案,同時向客戶端實時返回處理進度。所以實現了一個簡單demo,記錄一下。
一、服務端
- 新建了一個handler
2.SocketHandler.cs內容如下
using DotnetCoreWebAPI.Common; using DotnetCoreWebAPI.Models; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; using Newtonsoft.Json; using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Net.WebSockets; using System.Text; using System.Threading; using System.Threading.Tasks; namespace DotnetCoreWebAPI.Handler { public class SocketHandler { public const int BufferSize = 4096; public string basestringjson = string.Empty; WebSocket socket; SocketHandler(WebSocket socket) { this.socket = socket; } async Task EchoLoop() { var buffer = new byte[BufferSize]; var seg = new ArraySegment<byte>(buffer); while (this.socket.State == WebSocketState.Open) { var incoming = await this.socket.ReceiveAsync(seg, CancellationToken.None); string receivemsg = Encoding.UTF8.GetString(buffer, 0, incoming.Count); if (receivemsg == "get") { string stringJson = ""; List<AddressMatchProgressModel> infolist = new List<AddressMatchProgressModel>(); Hashtable newtable = CommonInfo.ProgressInfo; if (newtable != null) { try { foreach (DictionaryEntry i in newtable) { AddressMatchProgressModel pgmodel = new AddressMatchProgressModel(); pgmodel = (AddressMatchProgressModel)i.Value; infolist.Add(pgmodel); } } catch (Exception ex) { Console.WriteLine(ex.Message); } } stringJson = JsonConvert.SerializeObject(infolist); string userMsg = stringJson; byte[] x = Encoding.UTF8.GetBytes(userMsg); var outgoing = new ArraySegment<byte>(x); await this.socket.SendAsync(outgoing, WebSocketMessageType.Text, true, CancellationToken.None); } //var incoming = await this.socket.ReceiveAsync(seg, CancellationToken.None); //var outgoing = new ArraySegment<byte>(buffer, 0, incoming.Count); //await this.socket.SendAsync(outgoing, WebSocketMessageType.Text, true, CancellationToken.None); } } static async Task Acceptor(HttpContext hc, Func<Task> n) { if (!hc.WebSockets.IsWebSocketRequest) return; var socket = await hc.WebSockets.AcceptWebSocketAsync(); var h = new SocketHandler(socket); await h.EchoLoop(); } /// <summary> /// branches the request pipeline for this SocketHandler usage /// </summary> /// <param name="app"></param> public static void Map(IApplicationBuilder app) { app.UseWebSockets(); app.Use(SocketHandler.Acceptor); } } }
(ps:這裡遇到了一個小問題 ,記錄一下。我在另一個地方處理大檔案的,並把處理進度實時更新在一個全域性變數hashtable裡,然後在websocket服務端獲取這個變數的值,從而得到處理進度主動推送給客戶端。問題是hashtable在不斷的寫入同時在讀取,有時候便會出現movenext異常了。所以這裡將全域性變數hashtable賦值給了一個新的hashtable,這樣就可以保證在websocket服務端獲取進度資料的時候,這個hasntable的值是不會在遍歷的過程中變化的。)
3.startup.cs新增路由
二、客戶端
客戶端js指令碼寫的
//啟動websocket function startWebsocket() { var ws = new WebSocket("ws://localhost:9957/ws"); ws.onopen = function (evt) { console.log("Connection open ..."); isOpenWebSocket = true; ws.send("get"); }; ws.onmessage = function (evt) { isOpenWebSocket = true; console.log("Received Message: " + evt.data); var data = $.parseJSON(evt.data); if (data.length > 0) { var allfinish = true; for (var num in data) { var gid = data[num].Gid; var fileName = data[num].UploadFileName; var progress = data[num].Progress; if ($("#" + gid).length <= 0) { //當前進度條不存在 $("#progressbox").append("<div class='progress onepro' ><div id='" + gid + "' class='progress-bar' role='progressbar' aria-valuenow='60' aria-valuemin='0' aria-valuemax='100' style='width: 0%;'></div></div ><div id='" + gid + "_span' class='infospan'>" + fileName + "處理中</div ><div class='clearfloat'></div>"); } $("#" + gid).css("width", progress + "%").val("aria-valuenow", progress); if (progress == "100") { $("#" + gid + "_span").html(fileName + '處理完成,<a class="downloada" onclick="clickdown('' + gid + '')">下載</a>'); } else { allfinish = false; } } if (allfinish) { //進度全部100% ws.close(); isOpenWebSocket = false; } else { ws.send("get"); } } else { //進度資料不存在,斷開連線 ws.close(); isOpenWebSocket = false; } //ws.send(""); }; ws.onclose = function (evt) { isOpenWebSocket = false; console.log("Connection closed."); }; ws.onerror = function (evt) { write("Error: " + evt.data); }; //強制關閉瀏覽器 呼叫websocket.close(),進行正常關閉 window.onunload = function () { ws.close(); isOpenWebSocket = false; } }