后台我是采用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 及以上才行。