vue+webapi 实现WebSocket 推送

后台我是采用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;
                }
            }
        }

    }
}
View Code

前端使用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();
  }
}
View Code

为了方式测试,我使用另外一个接口调用 ,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 () {

      });
View Code

 最终实现效果

 

后面在同事的电脑上发现 WebSocket不行,经过多次对比排除,发现win 7系统不支持,需要win 8以上 ,以及server 2012 及以上才行。

原文地址:https://www.cnblogs.com/FlowLight/p/10381647.html