建立一個空的 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
參考連接: