zoukankan      html  css  js  c++  java
  • 【SignalR学习系列】3. SignalR实时高刷新率程序

    创建项目

    创建一个空的 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 {
                 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 {
                 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
  • 相关阅读:
    Cocos2d-x开发实例:使用Lambda 表达式
    Cocos2d-x实例:单点触摸事件
    Cocos2d-x中触摸事件
    Cocos2d-x开发实例介绍帧动画使用
    Cocos2d-x开发实例介绍特效演示
    c++ 类型转换
    boost的编译
    c/c++二级指针动态开辟内存
    基于RANSAC的点云面分割算法
    点到平面直线的距离和空间直线的距离
  • 原文地址:https://www.cnblogs.com/webenh/p/9560511.html
Copyright © 2011-2022 走看看