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 及以上才行。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM