后台我是采用webapi 方式 寫WebSocket,本來想用singler,后面有考慮到是vue 項目,就直接使用WebSocket了,因為不需要對ie做兼容。
后台具體代碼,因為可能多個瀏覽器 訪問都是不用的sockt 對象,需要分別存儲在字典list中,並在socket 鏈接關閉的時候銷毀,也思考過 while (true) 為什么不會陷入死循環,原因在於 WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);這句話,會阻塞 程序,只有等 有推送消息的時候,程序才會繼續執行!
using BozhouDMA.Model; using BozhouDMA.Service.Home; using BozhouDMAApi.Controllers.Base; using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; using System.Net.WebSockets; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Web; using System.Web.Http; using System.Web.WebSockets; using Newtonsoft.Json; namespace BozhouDMAApi.Controllers.Home { public class HomeController : ResultController { private HomeService hs = new HomeService(); public static Dictionary<string, WebSocket> dicSockets = new Dictionary<string, WebSocket>(); /// <summary> /// 創建socket連接 /// </summary> /// <returns></returns> [HttpGet] public HttpResponseMessage CreateSocket() { if (HttpContext.Current.IsWebSocketRequest) { HttpContext.Current.AcceptWebSocketRequest(ProcessWSChat); } return new HttpResponseMessage(HttpStatusCode.SwitchingProtocols); } /// <summary> /// 接收 報警程序推送數據 /// </summary> /// <param name="polices"></param> /// <returns></returns> [HttpPost] public Dictionary<string, object> PushPoliceInfo([FromBody] List<Alarm> polices) { try { if (dicSockets != null && dicSockets.Count > 0) { foreach (var dic in dicSockets) { var socket = dic.Value; if (socket.State == WebSocketState.Open) { var msg = JsonConvert.SerializeObject(polices); ArraySegment<byte> buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msg)); socket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None); } } } return this.Success("推送成功!"); } catch (Exception e) { return this.Fail("推送失敗," + e.Message); } } /// <summary> /// 接收前端發送的數據 /// </summary> /// <param name="arg"></param> /// <returns></returns> private async Task ProcessWSChat(AspNetWebSocketContext arg) { WebSocket socket = arg.WebSocket; string key = arg.SecWebSocketKey; if (!dicSockets.ContainsKey(key) ) { dicSockets.Add(key, socket); } while (true) { ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[1024 * 10]); WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None); if (socket.State == WebSocketState.Open) { //前端發送的命令 string message = Encoding.UTF8.GetString(buffer.Array, 0, result.Count); } else { dicSockets.Remove(key); break; } } } } }
前端使用es6 封裝一個類
let result = ''; let ws = null; export default class socketTool { static init () { if (ws == null) { ws = new WebSocket('ws://' + window.location.hostname + ':4110/api/Home/CreateSocket'); ws.onopen = function () { console.log('WebSocket連接成功!'); }; ws.onmessage = function (res) { console.log('推送數據:' + res.data); result = result + res.data; }; ws.onerror = function (error) { console.log('WebSocket連接失敗,錯誤:' + error); }; ws.onclose = function () { console.log('WebSocket連接關閉!'); }; } } // 發送數據到后端 static send (msg) { if (ws.readyState === WebSocket.OPEN) { ws.send(msg); } else { console.warn('WebSocket連接已關閉!'); } } // 關閉Socket static close () { ws.close(); } }
為了方式測試,我使用另外一個接口調用 ,webapi 作為推送:
testPush (param, callback) { http.post('/Home/PushPoliceInfo', param, function (res) { callback && callback(res); }); } let alarms = [{ "EventID": 1, "EventDate": "2019 - 02 - 14 16: 34: 19", "CustomerNo": "普通用戶:96719佟國印", "UserType": "1", "AlarmContent": "用水異常沒過下限 | 下限讀數:5.66666666666667 | 當前讀數:0", "AlarmType": "1", "AlarmHandle": null, "AlarmStatus": "1", "ID": 13607, "CreateDate": "2019 - 02 - 14 16: 34: 19", "ModifyDate": "2019 - 02 - 14 16: 34: 19", "Remark": null }, { "EventID": 1, "EventDate": "2019-02-14 16:34:19", "CustomerNo": "普通用戶:96718阮宜華", "UserType": "1", "AlarmContent": "用水異常沒過下限 | 下限讀數:2.20833333333333| 當前讀數:0", "AlarmType": "1", "AlarmHandle": null, "AlarmStatus": "1", "ID": 13606, "CreateDate": "2019-02-14 16:34:19", "ModifyDate": "2019-02-14 16:34:19", "Remark": null }]; homeServer.testPush(alarms, function () { });
最終實現效果


后面在同事的電腦上發現 WebSocket不行,經過多次對比排除,發現win 7系統不支持,需要win 8以上 ,以及server 2012 及以上才行。
