SignalR 1.x ile Yüksek Sıklıkta Gerçek Zamanlı
Tarafından Patrick Fletcher
Uyarı
Bu belgeler SignalR'nin en son sürümüne yönelik değildir. ASP.NET Core SignalR'ye göz atın.
Bu öğreticide, yüksek frekanslı mesajlaşma işlevselliği sağlamak için ASP.NET SignalR kullanan bir web uygulamasının nasıl oluşturulacağı gösterilmektedir. Bu durumda yüksek frekanslı mesajlaşma, sabit bir hızda gönderilen güncelleştirmeler anlamına gelir; bu uygulama söz konusu olduğunda, saniyede en fazla 10 ileti.
Bu öğreticide oluşturacağınız uygulama, kullanıcıların sürükleyebileceği bir şekil görüntüler. Şeklin diğer tüm bağlı tarayıcılardaki konumu, zamanlanmış güncelleştirmeler kullanılarak sürüklenen şeklin konumuyla eşleşecek şekilde güncelleştirilir.
Bu öğreticide tanıtılan kavramlar, gerçek zamanlı oyun ve diğer simülasyon uygulamalarında uygulamalara sahiptir.
Öğreticideki yorumlar kabul edilir. Öğreticiyle doğrudan ilgili olmayan sorularınız varsa bunları ASP.NET SignalR forumunu veya StackOverflow.com gönderebilirsiniz.
Genel Bakış
Bu öğreticide, bir nesnenin durumunu diğer tarayıcılarla gerçek zamanlı olarak paylaşan bir uygulamanın nasıl oluşturulacağı gösterilmektedir. Oluşturacağımız uygulamaya MoveShape adı verilir. MoveShape sayfasında kullanıcının sürükleyebileceği bir HTML Div öğesi görüntülenir; Kullanıcı Div'i sürüklediğinde, yeni konumu sunucuya gönderilir ve böylece diğer tüm bağlı istemcilere şeklin konumunu eşleşecek şekilde güncelleştirmelerini söyler.
Bu öğreticide oluşturulan uygulama, Damian Edwards'ın bir tanıtımını temel alır. Bu tanıtımı içeren bir video burada görülebilir.
Öğretici, şekil sürüklendikçe tetiklenen her olaydan SignalR iletilerinin nasıl gönderileceğini göstererek başlar. Her bağlı istemci, her ileti alındığında şeklin yerel sürümünün konumunu güncelleştirir.
Uygulama bu yöntemi kullanarak çalışacak olsa da, bu önerilen bir programlama modeli değildir, çünkü gönderilen ileti sayısının üst sınırı yoktur, bu nedenle istemciler ve sunucu iletilere boğulabilir ve performans düşebilir. İstemcide görüntülenen animasyon da kopuk olur çünkü şekil her yeni konuma sorunsuz bir şekilde taşınmak yerine her yöntem tarafından anında taşınır. Öğreticinin sonraki bölümlerinde, iletilerin istemci veya sunucu tarafından gönderilme hızını kısıtlayan bir zamanlayıcı işlevinin nasıl oluşturulacağı ve şeklin konumlar arasında sorunsuz bir şekilde nasıl taşınacağı gösterilmektedir. Bu öğreticide oluşturulan uygulamanın son sürümü Kod Galerisi'nden indirilebilir.
Bu öğretici aşağıdaki bölümleri içerir:
- Önkoşullar
- Projeyi oluşturma
- ASP.NET SignalR ve JQuery.UI NuGet paketlerini ekleme
- Temel uygulamayı oluşturma
- İstemci döngüsünü ekleme
- Sunucu döngüsünü ekleme
- İstemciye kesintisiz animasyon ekleme
- Diğer Adımlar
Önkoşullar
Bu öğretici için Visual Studio 2012 veya Visual Studio 2010 gerekir. Visual Studio 2010 kullanılırsa, proje .NET Framework 4.5 yerine .NET Framework 4 kullanır.
Visual Studio 2012 kullanıyorsanız, ASP.NET and Web Tools 2012.2 güncelleştirmesini yüklemeniz önerilir. Bu güncelleştirme yayımlama iyileştirmeleri, yeni işlevler ve yeni şablonlar gibi yeni özellikler içerir.
Visual Studio 2010'larınız varsa NuGet'in yüklü olduğundan emin olun.
Proje oluşturma
Bu bölümde projeyi Visual Studio'da oluşturacağız.
Dosyamenüsünden Yeni Proje'ye tıklayın.
Yeni Proje iletişim kutusunda Şablonlar'ın altında C# öğesini genişletin ve Web'i seçin.
Boş Web Uygulaması şablonunu ASP.NET seçin, projeye MoveShapeDemo adını verin ve Tamam'a tıklayın.
SignalR ve JQuery.UI NuGet Paketlerini Ekleme
Bir NuGet paketi yükleyerek bir projeye SignalR işlevselliği ekleyebilirsiniz. Bu öğreticide, şeklin sürüklenip animasyonlu olmasını sağlamak için JQuery.UI paketi de kullanılır.
Araçlar |'a tıklayın NuGet Paket Yöneticisi | Paket Yöneticisi Konsolu.
Paket yöneticisine aşağıdaki komutu girin.
Install-Package Microsoft.AspNet.SignalR -Version 1.1.3
SignalR paketi, bağımlılık olarak bir dizi diğer NuGet paketini yükler. Yükleme tamamlandığında, ASP.NET bir uygulamada SignalR kullanmak için gereken tüm sunucu ve istemci bileşenlerine sahip olursunuz.
JQuery ve JQuery.UI paketlerini yüklemek için paket yöneticisi konsoluna aşağıdaki komutu girin.
Install-Package jQuery.ui.combined
Temel uygulamayı oluşturma
Bu bölümde, her fare taşıma olayı sırasında şeklin konumunu sunucuya gönderen bir tarayıcı uygulaması oluşturacağız. Sunucu daha sonra bu bilgileri alınan diğer tüm bağlı istemcilere yayınlar. Bu uygulamayı sonraki bölümlerde genişleteceğiz.
Çözüm Gezgini'da projeye sağ tıklayın ve Ekle, Sınıf... öğesini seçin. Sınıfı MoveShapeHub olarak adlandırın ve Ekle'ye tıklayın.
Yeni MoveShapeHub sınıfındaki kodu aşağıdaki kodla değiştirin.
using System; using System.Collections.Generic; using System.Linq; using Microsoft.AspNet.SignalR; using Microsoft.AspNet.SignalR.Hubs; using Newtonsoft.Json; namespace MoveShapeDemo { 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; } } }
Yukarıdaki
MoveShapeHub
sınıf, SignalR hub'ının bir uygulamasıdır. SignalR ile Çalışmaya Başlama öğreticisinde olduğu gibi hub'da da istemcilerin doğrudan çağıracağı bir yöntem vardır. Bu durumda, istemci şeklin yeni X ve Y koordinatlarını içeren bir nesneyi sunucuya gönderir ve ardından diğer tüm bağlı istemcilere yayınlanır. SignalR, JSON kullanarak bu nesneyi otomatik olarak seri hale getirecektir.İstemciye (
ShapeModel
) gönderilecek nesne, şeklin konumunu depolamak için üyeler içerir. Sunucudaki nesnenin sürümü, belirli bir istemcinin kendi verilerini göndermemesi için hangi istemcinin verilerinin depolandığını izlemek için bir üye de içerir. Bu üye, seri hale getirilip istemciye gönderilmesini korumak için özniteliğini kullanırJsonIgnore
.Ardından, uygulama başlatıldığında hub'ı ayarlayacağız. Çözüm Gezgini'da projeye sağ tıklayın ve ardından Ekle | öğesine tıklayın. Genel Uygulama Sınıfı. Varsayılan Genel adını kabul edin ve Tamam'a tıklayın.
Global.asax.cs sınıfında sağlanan using deyimlerinden sonra aşağıdaki
using
deyimi ekleyin.using System.Web.Routing;
SignalR için varsayılan yolu kaydetmek için Global sınıfının yöntemine aşağıdaki kod
Application_Start
satırını ekleyin.RouteTable.Routes.MapHubs();
global.asax dosyanız aşağıdaki gibi görünmelidir:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Security; using System.Web.SessionState; using System.Web.Routing; namespace MoveShapeDemo { public class Global : System.Web.HttpApplication { protected void Application_Start(object sender, EventArgs e) { RouteTable.Routes.MapHubs(); } } }
Ardından istemciyi ekleyeceğiz. Çözüm Gezgini'da projeye sağ tıklayın ve ardından Ekle | öğesine tıklayın. Yeni Öğe. Yeni Öğe Ekle iletişim kutusunda Html Sayfası'nı seçin. Sayfaya uygun bir ad verin ( Default.htmlgibi) ve Ekle'ye tıklayın.
Çözüm Gezgini'da, yeni oluşturduğunuz sayfaya sağ tıklayın ve Başlangıç Sayfası Olarak Ayarla'ya tıklayın.
HTML sayfasındaki varsayılan kodu aşağıdaki kod parçacığıyla değiştirin.
Not
Aşağıdaki betik başvurularının Betikler klasöründe projenize eklenen paketlerle eşleştiğini doğrulayın. Visual Studio 2010'da projeye eklenen JQuery ve SignalR sürümü aşağıdaki sürüm numaralarıyla eşleşmeyebilir.
<!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-1.6.4.js"></script> <script src="Scripts/jquery-ui-1.10.2.js"></script> <script src="Scripts/jquery.signalR-1.0.1.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>
Yukarıdaki HTML ve JavaScript kodu Shape adlı kırmızı bir Div oluşturur, jQuery kitaplığını kullanarak şeklin sürükleme davranışını etkinleştirir ve şeklin olayını kullanarak şeklin
drag
konumunu sunucuya gönderir.F5 tuşuna basarak uygulamayı başlatın. Sayfanın URL'sini kopyalayın ve ikinci bir tarayıcı penceresine yapıştırın. Şekli tarayıcı pencerelerinden birinde sürükleyin; diğer tarayıcı penceresindeki şeklin hareket etmesi gerekir.
İstemci döngüsünü ekleme
Her fare taşıma olayında şeklin konumunun gönderilmesi gereksiz miktarda ağ trafiği oluşturacağı için istemciden gelen iletilerin kısıtlanması gerekir. Sabit bir hızda sunucuya yeni konum bilgileri gönderen bir döngü ayarlamak için javascript setInterval
işlevini kullanacağız. Bu döngü, bir oyunun veya başka bir simülasyonun tüm işlevlerini yönlendiren ve sürekli olarak adlandırılan bir işlev olan "oyun döngüsünün" çok temel bir gösterimidir.
HTML sayfasındaki istemci kodunu aşağıdaki kod parçacığıyla eşleşecek şekilde güncelleştirin.
<!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-1.6.4.js"></script> <script src="Scripts/jquery-ui-1.10.2.js"></script> <script src="Scripts/jquery.signalR-1.0.1.js"></script> <script src="/signalr/hubs"></script> <script> $(function () { var moveShapeHub = $.connection.moveShapeHub, $shape = $("#shape"), // Send a maximum of 10 messages per second // (mouse movements trigger a lot of messages) messageFrequency = 10, // 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>
Yukarıdaki güncelleştirme, sabit bir frekansta çağrılan işlevi ekler
updateServerModel
. Bayrak gönderilecek yeni konum verileri olduğunu gösterdiğindemoved
bu işlev konum verilerini sunucuya gönderir.F5 tuşuna basarak uygulamayı başlatın. Sayfanın URL'sini kopyalayın ve ikinci bir tarayıcı penceresine yapıştırın. Şekli tarayıcı pencerelerinden birinde sürükleyin; şeklin diğer tarayıcı penceresinde hareket etmesi gerekir. Sunucuya gönderilen ileti sayısı azaltılacağından, animasyon önceki bölümde olduğu gibi düzgün görünmez.
Sunucu döngüsünü ekleme
Geçerli uygulamada, sunucudan istemciye gönderilen iletiler alındığı sıklıkta dışarı gider. Bu, istemcide görüldüğü gibi benzer bir sorun sunar; iletileri gerektiğinden daha sık gönderilebilir ve bunun sonucunda bağlantı sular altında kalır. Bu bölümde, giden iletilerin hızını kısıtlayan bir zamanlayıcı uygulamak için sunucunun nasıl güncelleştirildiği açıklanır.
öğesinin içeriğini
MoveShapeHub.cs
aşağıdaki kod parçacığıyla değiştirin.using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Threading; using Microsoft.AspNet.SignalR; using Newtonsoft.Json; namespace MoveShapeDemo { public class Broadcaster { private readonly static Lazy<Broadcaster> _instance = new Lazy<Broadcaster>(() => new Broadcaster()); // We're going to broadcast to all clients a maximum of 25 times per second private readonly TimeSpan BroadcastInterval = TimeSpan.FromMilliseconds(40); 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; } } }
Yukarıdaki kod, .NET framework'ten sınıfını kullanarak giden iletileri kısıtlayan sınıfını eklemek
Broadcaster
için istemciyiTimer
genişletir.Hub'ın kendisi geçici olduğundan (her gerektiğinde oluşturulur),
Broadcaster
tekil olarak oluşturulur. Gecikmeli başlatma (.NET 4'te kullanıma sunulan), ilk hub örneğinin zamanlayıcı başlatılmadan önce tamamen oluşturulmasını sağlayarak oluşturulmasını gerekene kadar ertelemek için kullanılır.İstemcilerin
UpdateShape
işlevine yapılan çağrı daha sonra hub'ınUpdateModel
yönteminden taşınır, böylece gelen iletiler alındığında artık hemen çağrılmaması sağlanır. Bunun yerine, istemcilere iletiler, sınıfın içindenBroadcaster
zamanlayıcı tarafından_broadcastLoop
yönetilen saniyede 25 çağrı hızında gönderilir.Son olarak, istemci yöntemini doğrudan hub'dan çağırmak yerine sınıfının
Broadcaster
kullanarak şu anda işletim hub'ına (_hubContext
)GlobalHost
bir başvuru alması gerekir.F5 tuşuna basarak uygulamayı başlatın. Sayfanın URL'sini kopyalayın ve ikinci bir tarayıcı penceresine yapıştırın. Şekli tarayıcı pencerelerinden birinde sürükleyin; şeklin diğer tarayıcı penceresinde hareket etmesi gerekir. Tarayıcıda önceki bölümden görünür bir fark olmayacaktır, ancak istemciye gönderilen ileti sayısı kısıtlanır.
İstemciye düzgün animasyon ekleme
Uygulama neredeyse tamamlandı, ancak sunucu iletilerine yanıt olarak taşınan şeklin istemcideki hareketinde bir geliştirme daha yapabiliriz. Şeklin konumunu sunucu tarafından verilen yeni konuma ayarlamak yerine JQuery UI kitaplığının animate
işlevini kullanarak şekli geçerli ve yeni konumu arasında sorunsuz bir şekilde taşıyacağız.
İstemcinin
updateShape
yöntemini aşağıda vurgulanan kod gibi görünecek şekilde güncelleştirin:<!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-1.6.4.js"></script> <script src="Scripts/jquery-ui-1.10.2.js"></script> <script src="Scripts/jquery.signalR-1.0.1.js"></script> <script src="/signalr/hubs"></script> <script> $(function () { var moveShapeHub = $.connection.moveShapeHub, $shape = $("#shape"), // Send a maximum of 10 messages per second // (mouse movements trigger a lot of messages) messageFrequency = 10, // 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; // Gradually move the shape towards the new location (interpolate) // The updateRate is used as the duration because by the time // we get to the next location we want to be at the "last" location // We also clear the animation queue so that we start a new // animation and don't lag behind. $shape.animate(shapeModel, { duration: updateRate, queue: false }); }; $.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>
Yukarıdaki kod, animasyon aralığı boyunca şekli eski konumdan sunucu tarafından verilen yeniye taşır (bu örnekte 100 milisaniye). Şekil üzerinde çalışan önceki animasyonlar, yeni animasyon başlamadan önce temizlenir.
F5 tuşuna basarak uygulamayı başlatın. Sayfanın URL'sini kopyalayın ve ikinci bir tarayıcı penceresine yapıştırın. Şekli tarayıcı pencerelerinden birinde sürükleyin; şeklin diğer tarayıcı penceresinde hareket etmesi gerekir. Şeklin diğer penceredeki hareketi, gelen ileti başına bir kez ayarlamak yerine zaman içinde ilişkilendirilmiş olduğundan daha az hıyarlı görünmelidir.
Diğer Adımlar
Bu öğreticide, istemciler ve sunucular arasında yüksek frekanslı iletiler gönderen bir SignalR uygulamasını programlamayı öğrendiniz. Bu iletişim paradigması, SignalR ile oluşturulan ShootR oyunu gibi çevrimiçi oyunlar ve diğer simülasyonlar geliştirmek için kullanışlıdır.
Bu öğreticide oluşturulan uygulamanın tamamı Kod Galerisi'nden indirilebilir.
SignalR geliştirme kavramları hakkında daha fazla bilgi edinmek için SignalR kaynak kodu ve kaynakları için aşağıdaki siteleri ziyaret edin:
Geri Bildirim
https://aka.ms/ContentUserFeedback.
Çok yakında: 2024 boyunca, içerik için geri bildirim mekanizması olarak GitHub Sorunları’nı kullanımdan kaldıracak ve yeni bir geri bildirim sistemiyle değiştireceğiz. Daha fazla bilgi için bkz.Gönderin ve geri bildirimi görüntüleyin