Websocket在Asp.net webApi(.net framework)上的应用

之前在写MES系统看板部分的web api的时候,都是通过Ajax在规定时间内轮询调用web api,这样简单省事,但是当看板多了(并发量上来)以后,比较消耗服务器的性能,所以最近研究了websocket,希望使用websocket只在数据发生变化时向客户端推送数据。

1、控制器

 public class UserController : ApiController
{
        [HttpGet]
        [Route("info")]
        public HttpResponseMessage GetConnect()
        {
            //在服务器端接受WebSocket请求
            HttpContext.Current.AcceptWebSocketRequest(WebsocketHelper.ProcessRequest);
           
            //Response.
            return Request.CreateResponse(HttpStatusCode.SwitchingProtocols);
        }
}

2、Websocket类

 public static class WebsocketHelper
    {
        /// <summary>
        /// 记录客户端连接
        /// </summary>
        private static Dictionary<string, WebSocket> webSockets=new Dictionary<string, WebSocket>();
        /// <summary>
        /// 接受信息
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public async static Task ProcessRequest(AspNetWebSocketContext context)
        {
            try
            {
                //获取路由
                string route = context.RawUrl;
                if (route.Contains("?"))
                {
                    route = route.Split('?')[0];
                }
                string key = context.UserHostAddress + route;
                //传入的context中有当前的websocket对象
                var socket = context.WebSocket;
                //此处将web socket对象加入一个静态字典中.
                if (!webSockets.ContainsKey(key))
                {
                    //将IP地址和路由设置为hashTable的key值,若hashTable中存在该IP地址则不再添加
                    webSockets.Add(key, socket);
                }
                //进入一个无限循环,当websocket close时循环结束
                while (true)
                {
                    //关闭连接
                    var buffer = new ArraySegment<byte>(new byte[1024]);
                    //对web socket进行异步接收数据
                    var receivedResult = await socket.ReceiveAsync(buffer, CancellationToken.None);
                    if (receivedResult.MessageType == WebSocketMessageType.Close)
                    {
                        //如果client发起close请求,对client进行ack
                        await socket.CloseAsync(WebSocketCloseStatus.Empty, string.Empty, CancellationToken.None);
                        webSockets.Remove(key);
                        break;
                    }
                }
            }
            catch (Exception ex)
            {

            }
        }

        /// <summary>
        /// 将数据发送给所有已连接的客户端
        /// </summary>
        /// <param name="data"></param>
        /// <param name="route">接口路由</param>
        public static void SendAll(string data, string route)
        {
            var recvBytes = Encoding.UTF8.GetBytes(data);
            var sendBuffer = new ArraySegment<byte>(recvBytes);
            if (webSockets.Any())
            {
                var webs = webSockets.Where(w => w.Key.Contains(route)).ToList();
                if (webs != null)
                {
                    foreach (var item in webs)
                    {
                        item.Value.SendAsync(sendBuffer, WebSocketMessageType.Text, true, CancellationToken.None);
                    }
                }
            }
        }
    }

3、定时获取数据并判断数据是否变化

 public class DataTimer
{
        /// <summary>
        /// 定时获取数据库数据并赋值给Data类
        /// </summary>
        public void ChangeData()
        {
            //用定时器设置多长时间,客户端首次连接就会有相应的延迟时间
            DBData dBDataTimer = new DBData();
            Timer timer = new Timer();
            timer.Interval = 3000;
            timer.AutoReset = true;
            timer.Enabled = true;
            timer.Elapsed += delegate
            {
                string data = GetData();
                if (data != dBDataTimer.Data)
                {
                    WebsocketHelper.SendAll(data, "info");
                    dBDataTimer.Data = data;
                }
            };
            timer.Start();
        }
        /// <summary>
        /// 获取数据库数据
        /// </summary>
        /// <returns></returns>
        public string GetData()
        {
            List<Inform> inform_list = new List<Inform>();
            DataTable inform_dt = SqlHelper.ExecuteTable("select * from inform where state='true'");
            for (int i = 0; i < inform_dt.Rows.Count; i++)
            {
                Inform data = new Inform();
                data.Id = inform_dt.Rows[i].Field<Int32>("id");
                data.Name = inform_dt.Rows[i].Field<string>("name");
                data.State = inform_dt.Rows[i].Field<bool>("state");
                inform_list.Add(data);
            }
            string ret = JsonConvert.SerializeObject(new { type = "info", data = inform_list });
            return ret;
        }
        private class Inform
        {
            public int Id { get; set; }
            public string Name { get; set; }
            public bool State { get; set; }
        }
}

public class DBData
{
     public string Data { get; set; }
}

4、在Global.asax中调用定时获取数据的方法

 public class WebApiApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            GlobalConfiguration.Configure(WebApiConfig.Register);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
            new DataTimer().ChangeData();
        }
    }

以上就是websocket在asp.net web api中的用法,本人入行不久,不足之处敬请谅解,谢谢!!!

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值