码迷,mamicode.com
首页 > 其他好文 > 详细

【SignalR学习系列】3. SignalR实时高刷新率程序

时间:2017-07-22 22:20:34      阅读:712      评论:0      收藏:0      [点我收藏+]

标签:font   maps   visit   new   creation   ant   overview   loop   ack   

创建项目

创建一个空的 Web 项目,并在 Nuget 里面添加 SignalR,jQuery UI 包,添加以后项目里包含了 jQuery,jQuery.UI ,和 SignalR 的脚本。

技术分享

 

创建基础应用

添加一个 SignalR Hub 类,并命名为 MoveShapeHub ,更新代码。

技术分享

using Microsoft.AspNet.SignalR;
using Newtonsoft.Json;

namespace SignalRDemo3
{
    public class MoveShapeHub : Hub
    {
        public void UpdateModel(ShapeModel clientModel)
        {
            clientModel.LastUpdatedBy = Context.ConnectionId;
            // Update the shape model within our broadcaster
            Clients.AllExcept(clientModel.LastUpdatedBy).updateShape(clientModel);
        }
    }

    public class ShapeModel
    {
        // We declare Left and Top as lowercase with 
        // JsonProperty to sync the client and server models
        [JsonProperty("left")]
        public double Left { get; set; }
        [JsonProperty("top")]
        public double Top { get; set; }
        // We don‘t want the client to get the "LastUpdatedBy" property
        [JsonIgnore]
        public string LastUpdatedBy { get; set; }
    }
}

当程序启动的时候启动Hub

添加 Owin 类,并在里面配置 SignalR

技术分享

using Microsoft.Owin;
using Owin;

[assembly: OwinStartup(typeof(SignalRDemo3.Startup))]

namespace SignalRDemo3
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=316888
            app.MapSignalR();
        }
    }
}

 

添加客户端

添加一个名为 Index 的 html 页面,并设置为启动页面。

<!DOCTYPE html>
<html>
<head>
    <title>SignalR MoveShape Demo</title>
    <style>
        #shape {
            width: 100px;
            height: 100px;
            background-color: #FF0000;
        }
    </style>
</head>
<body>
    <script src="Scripts/jquery-3.1.1.min.js"></script>
    <script src="Scripts/jquery-ui-1.12.1.min.js"></script>
    <script src="Scripts/jquery.signalR-2.2.2.js"></script>
    <script src="/signalr/hubs"></script>
    <script>
        $(function () {
            var moveShapeHub = $.connection.moveShapeHub,
                $shape = $("#shape"),
                shapeModel = {
                    left: 0,
                    top: 0
                };
            moveShapeHub.client.updateShape = function (model) {
                shapeModel = model;
                $shape.css({ left: model.left, top: model.top });
            };
            $.connection.hub.start().done(function () {
                $shape.draggable({
                    drag: function () {
                        shapeModel = $shape.offset();
                        moveShapeHub.server.updateModel(shapeModel);
                    }
                });
            });
        });
    </script>

    <div id="shape" />
</body>
</html>

上面的 Html 和 JavaScript 代码创建一个名为 Shape 的 Div ,并且通过jQuery库给 Shape 提供了拖拽功能,并通过拖拽事件向服务器发送 Shape 的当前位置。

现在可以 F5 启动调试看效果,当程序启动以后,打开另一个浏览器窗口,输入地址,你可以在一个窗口拖拽红色的 Shape,另一个窗口的 Shape 也会跟着动。

技术分享

 

 

添加客户端循环

如果每次鼠标移动都发送数据到服务端,那就需要很多网络流量,我们必须降低发送数据的频率。我们可以通过 setInterval 函数,设置一个固定的时间来发送数据到服务器。

<!DOCTYPE html>
<html>
<head>
    <title>SignalR MoveShape Demo</title>
    <style>
        #shape {
            width: 100px;
            height: 100px;
            background-color: #FF0000;
        }
    </style>
</head>
<body>
    <script src="Scripts/jquery-3.1.1.min.js"></script>
    <script src="Scripts/jquery-ui-1.12.1.min.js"></script>
    <script src="Scripts/jquery.signalR-2.2.2.js"></script>
    <script src="/signalr/hubs"></script>
    <script>
        $(function () {
            var moveShapeHub = $.connection.moveShapeHub,
                $shape = $("#shape"),
                // Send a maximum of 2 messages per second
                // (mouse movements trigger a lot of messages)
                messageFrequency = 2,
                // Determine how often to send messages in
                // time to abide by the messageFrequency
                updateRate = 1000 / messageFrequency,
                shapeModel = {
                    left: 0,
                    top: 0
                },
                moved = false;
            moveShapeHub.client.updateShape = function (model) {
                shapeModel = model;
                $shape.css({ left: model.left, top: model.top });
            };
            $.connection.hub.start().done(function () {
                $shape.draggable({
                    drag: function () {
                        shapeModel = $shape.offset();
                        moved = true;
                    }
                });
                // Start the client side server update interval
                setInterval(updateServerModel, updateRate);
            });
            function updateServerModel() {
                // Only update server if we have a new movement
                if (moved) {
                    moveShapeHub.server.updateModel(shapeModel);
                    moved = false;
                }
            }
        });
    </script>

    <div id="shape" />
</body>
</html>

可以用上面的代码更新刚才的 Index.html页面,然后F5调试,可以发现现在拖动一个 Shape 以后在另一个浏览器里的 Shape 半秒钟才会更新。

 

增加服务端循环

更新 MoveShapeHub.cs

using Microsoft.AspNet.SignalR;
using Newtonsoft.Json;
using System;
using System.Threading;

namespace SignalRDemo3
{
    public class Broadcaster
    {
        private readonly static Lazy<Broadcaster> _instance =
            new Lazy<Broadcaster>(() => new Broadcaster());
        // We‘re going to broadcast to all clients once 2 second
        private readonly TimeSpan BroadcastInterval =
            TimeSpan.FromMilliseconds(2000);
        private readonly IHubContext _hubContext;
        private Timer _broadcastLoop;
        private ShapeModel _model;
        private bool _modelUpdated;
        public Broadcaster()
        {
            // Save our hub context so we can easily use it 
            // to send to its connected clients
            _hubContext = GlobalHost.ConnectionManager.GetHubContext<MoveShapeHub>();
            _model = new ShapeModel();
            _modelUpdated = false;
            // Start the broadcast loop
            _broadcastLoop = new Timer(
                BroadcastShape,
                null,
                BroadcastInterval,
                BroadcastInterval);
        }
        public void BroadcastShape(object state)
        {
            // No need to send anything if our model hasn‘t changed
            if (_modelUpdated)
            {
                // This is how we can access the Clients property 
                // in a static hub method or outside of the hub entirely
                _hubContext.Clients.AllExcept(_model.LastUpdatedBy).updateShape(_model);
                _modelUpdated = false;
            }
        }
        public void UpdateShape(ShapeModel clientModel)
        {
            _model = clientModel;
            _modelUpdated = true;
        }
        public static Broadcaster Instance
        {
            get
            {
                return _instance.Value;
            }
        }
    }

    public class MoveShapeHub : Hub
    {
        // Is set via the constructor on each creation
        private Broadcaster _broadcaster;
        public MoveShapeHub()
            : this(Broadcaster.Instance)
        {
        }
        public MoveShapeHub(Broadcaster broadcaster)
        {
            _broadcaster = broadcaster;
        }
        public void UpdateModel(ShapeModel clientModel)
        {
            clientModel.LastUpdatedBy = Context.ConnectionId;
            // Update the shape model within our broadcaster
            _broadcaster.UpdateShape(clientModel);
        }
    }

    public class ShapeModel
    {
        // We declare Left and Top as lowercase with 
        // JsonProperty to sync the client and server models
        [JsonProperty("left")]
        public double Left { get; set; }
        [JsonProperty("top")]
        public double Top { get; set; }
        // We don‘t want the client to get the "LastUpdatedBy" property
        [JsonIgnore]
        public string LastUpdatedBy { get; set; }
    }
}

上面的代码新建了一个 Broadcaster 类,通过类 Timer 来进行节流。

因为 Hub 实例每次都会重新创建,所以只能创建一个 Broadcaster 的单例模型。调用客户端 UpdateShape 的方法被移出了 hub 。现在它通过类 Broadcaster 来管理,通过名为 _broadcastLoop 的 timer 每两秒更新一次。

最后因为不能直接在 hub 里调用客户端方法,类 Broadcaster 需要通过 GlobalHost 来获取到当前进行操作的 hub。

最终使用 F5 进行调试,虽然客户端设置了半秒一次的刷新,但是因为服务器端设置了2秒一次刷新,所以你在当前浏览器里移动 Shape ,两秒钟过后另一个浏览器里的 Shape 才会移动到当前位置。

 

源代码链接:

链接: https://pan.baidu.com/s/1o8NXwTW 密码: 5r5i

 

参考链接:

https://docs.microsoft.com/zh-cn/aspnet/signalr/overview/getting-started/tutorial-high-frequency-realtime-with-signalr

【SignalR学习系列】3. SignalR实时高刷新率程序

标签:font   maps   visit   new   creation   ant   overview   loop   ack   

原文地址:http://www.cnblogs.com/Soulless/p/7222891.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!