【SignalR學習系列】3. SignalR實時高刷新率程序

建立項目

建立一個空的 Web 項目,並在 Nuget 裏面添加 SignalR,jQuery UI 包,添加之後項目裏包含了 jQuery,jQuery.UI ,和 SignalR 的腳本。css

 

建立基礎應用

添加一個 SignalR Hub 類,並命名爲 MoveShapeHub ,更新代碼。html

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; }
    }
}

當程序啓動的時候啓動Hubjquery

添加 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 也會跟着動。app

 

 

添加客戶端循環

若是每次鼠標移動都發送數據到服務端,那就須要不少網絡流量,咱們必須下降發送數據的頻率。咱們能夠經過 setInterval 函數,設置一個固定的時間來發送數據到服務器。ide

<!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.csoop

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

相關文章
相關標籤/搜索