【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 {
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();
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
参考链接:
【SignalR学习系列】3. SignalR实时高刷新率程序的更多相关文章
- SignalR学习笔记(二)高并发应用
虽然SignalR借助Websocket提供了很强大的实时通讯能力,但是在有些实时通讯非常频繁的场景之下,如果使用不当,还是会导致服务器,甚至客户端浏览器崩溃. 以下是一个实时拖拽方块项目的优化过程 ...
- 【SignalR学习系列】1. SignalR理论介绍
什么是SignalR? ASP.NET SignalR 是一个让 ASP.NET开发者可以简单地给自己的程序添加即时通讯功能的开发库.即时通讯功能可以直接从服务器端给在线的客户端发送数据,而不用等待客 ...
- 【SignalR学习系列】4. SignalR广播程序
创建项目 创建一个空的 Web 项目,并在 Nuget 里面添加 SignalR,jQuery UI 包,添加以后项目里包含了 jQuery,jQuery.UI ,和 SignalR 的脚本. 服务端 ...
- 【SignalR学习系列】8. SignalR Hubs Api 详解(.Net C# 客户端)
建立一个 SignalR 连接 var hubConnection = new HubConnection("http://www.contoso.com/"); IHubProx ...
- 【SignalR学习系列】7. SignalR Hubs Api 详解(JavaScript 客户端)
SignalR 的 generated proxy 服务端 public class ContosoChatHub : Hub { public void NewContosoChatMessage( ...
- 【SignalR学习系列】6. SignalR Hubs Api 详解(C# Server 端)
如何注册 SignalR 中间件 为了让客户端能够连接到 Hub ,当程序启动的时候你需要调用 MapSignalR 方法. 下面代码显示了如何在 OWIN startup 类里面定义 SignalR ...
- 【SignalR学习系列】5. SignalR WPF程序
首先创建 WPF Server 端,新建一个 WPF 项目 安装 Nuget 包 替换 MainWindows 的Xaml代码 <Window x:Class="WPFServer.M ...
- 【SignalR学习系列】2. 第一个SignalR程序
新建项目 1.使用VisualStudio 2015 新建一个Web项目 2.选择空模板 3.添加一个新的SignalR Hub Class (v2)类文件,并修改类名为ChatHub 4.修改Cha ...
- SpringCloud学习系列之一 ----- 搭建一个高可用的注册中心(Eureka)
前言 本篇主要介绍的是SpringCloud相关知识.微服务架构以及搭建一个高可用的服务注册与发现的服务模块(Eureka). SpringCloud介绍 Spring Cloud是在Spring B ...
随机推荐
- 去除MyEclipse频繁弹出的Update Progress窗口
方法1: 1.关闭updating index Window => Preferences => Myeclipse Enterprise Workbench => Maven4My ...
- 记一次使用搬瓦工VPS的经历
自己因为有需求上Google,以前是通过修改hosts的方法实现访问Google,但是最近不知道为什么改hosts后还是无法访问Google,于是决定搭建VPS来实现科学上网,看了一下价格,作为穷逼学 ...
- mysql update 批量更新
UPDATE cntheater SET title = (SELECT title FROM cntheater_copy WHERE cntheater.id = cntheater_copy.i ...
- 15套java互联网架构师、高并发、集群、负载均衡、高可用、数据库设计、缓存、性能优化、大型分布式 项目实战视频教程
* { font-family: "Microsoft YaHei" !important } h1 { color: #FF0 } 15套java架构师.集群.高可用.高可扩 展 ...
- PHP安装phpredis扩展
phpredis 的github地址:https://github.com/nicolasff/phpredis第一步:切换到指定的目录,然后wget https://github.com/nicol ...
- 远程连接mysql 授权方法详解
今在服务器上 有mysql 数据库,远程访问,不想公布root账户,所以,创建了demo账户,允许demo账户在任何地方都能访问mysql数据库中shandong库. 方案一: 在安装mysql的机器 ...
- Spring MVC使用样例
Spring MVC使用样例 步骤1:添加Spring的相关依赖 1 <dependency> 2 3 <groupId>com.alibaba.external</gr ...
- 怎么利用composer创建laravel项目
前提:已经安装了composer的电脑 创建laravel项目: 第一步: 找到你要创建文件的地方 然后打开doc,输入:composer create_project laravel/laravel ...
- 计算机浏览器存储技术cookie、sessionStorage、localStorage
HTTP无状态协议是指协议对于事务处理没有记忆能力.会话跟踪协议的状态是指下一次传输可以"记住"这次传输信息的能力,无状态是指同一个会话(注意什么叫同一个会话)的连续两个请求互相不 ...
- Mysql元数据分析
Mysql元数据分析 @(基础技术) 一.information_schema库 information_schema库中的表,保存的是Mysql的元数据. 官网元数据表介绍 InnoDB相关的表介绍 ...