Aracılığıyla paylaş


Öğretici: SignalR 2 ile yüksek frekanslı gerçek zamanlı uygulama oluşturma

Bu öğreticide, yüksek frekanslı mesajlaşma işlevselliği sağlamak için ASP.NET SignalR 2 kullanan bir web uygulamasının nasıl oluşturulacağı gösterilmektedir. Bu durumda, "yüksek frekanslı mesajlaşma", sunucunun güncelleştirmeleri sabit bir hızda gönderdiği anlamına gelir. Saniyede en fazla 10 ileti gönderirsiniz.

Oluşturduğunuz uygulama, kullanıcıların sürükleyebileceği bir şekil görüntüler. Sunucu, zamanlanmış güncelleştirmeleri kullanarak şeklin tüm bağlı tarayıcılardaki konumunu sürüklenen şeklin konumuyla eşleşecek şekilde güncelleştirir.

Bu öğreticide tanıtılan kavramlar, gerçek zamanlı oyun ve diğer simülasyon uygulamalarında uygulamalara sahiptir.

Bu öğreticide şunları yaptınız:

  • Projeyi ayarlama
  • Temel uygulamayı oluşturma
  • Uygulama başlatıldığında hub'a eşleme
  • İstemciyi ekleme
  • Uygulamayı çalıştırma
  • İstemci döngüsünü ekleme
  • Sunucu döngüsünü ekleme
  • Düz animasyon ekleme

Uyarı

Bu belgeler SignalR'nin en son sürümüne yönelik değildir. ASP.NET Core SignalR'ye göz atın.

Önkoşullar

Projeyi ayarlama

Bu bölümde, projeyi Visual Studio 2017'de oluşturacaksınız.

Bu bölümde Visual Studio 2017'yi kullanarak boş bir ASP.NET Web Uygulaması oluşturma ve SignalR ve jQuery.UI kitaplıklarını ekleme adımları gösterilmektedir.

  1. Visual Studio'da bir ASP.NET Web Uygulaması oluşturun.

    Web oluşturma

  2. Yeni ASP.NET Web Uygulaması - MoveShapeDemo penceresinde Boş seçeneğini seçili bırakın ve Tamam'ı seçin.

  3. Çözüm Gezgini'de projeye sağ tıklayın ve Yeni Öğe Ekle'yi>seçin.

  4. Yeni Öğe Ekle - MoveShapeDemo'da Yüklü>Visual C#>Web>SignalR'yi ve ardından SignalR Hub Sınıfı (v2) öğesini seçin.

  5. Sınıfı MoveShapeHub olarak adlandırın ve projeye ekleyin.

    Bu adım MoveShapeHub.cs sınıf dosyasını oluşturur. Aynı anda, projeye SignalR'yi destekleyen bir dizi betik dosyası ve derleme başvurusu ekler.

  6. Araçlar>NuGet Paket Yöneticisi> Paket Yöneticisi Konsolu'nu seçin.

  7. Paket Yöneticisi Konsolu'nda şu komutu çalıştırın:

    Install-Package jQuery.UI.Combined
    

    komutu jQuery kullanıcı arabirimi kitaplığını yükler. Şekle animasyon eklemek için bunu kullanırsınız.

  8. Çözüm Gezgini'da Betikler düğümünü genişletin.

    Betik kitaplığı başvuruları

    Projede jQuery, jQueryUI ve SignalR için betik kitaplıkları görünür.

Temel uygulamayı oluşturma

Bu bölümde bir tarayıcı uygulaması oluşturacaksınız. Uygulama, her fare taşıma olayı sırasında şeklin konumunu sunucuya gönderir. Sunucu bu bilgileri diğer tüm bağlı istemcilere gerçek zamanlı olarak yayınlar. Bu uygulama hakkında daha fazla bilgiyi sonraki bölümlerde öğreneceksiniz.

  1. MoveShapeHub.cs dosyasını açın.

  2. MoveShapeHub.cs dosyasındaki kodu şu kodla değiştirin:

    using Microsoft.AspNet.SignalR;
    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; }
        }
    }
    
  3. Dosyayı kaydedin.

MoveShapeHub sınıfı, SignalR hub'ının bir uygulamasıdır. SignalR ile Çalışmaya Başlama öğreticisinde olduğu gibi, hub'da istemcilerin doğrudan çağırdığı bir yöntem vardır. Bu durumda, istemci şeklin yeni X ve Y koordinatlarını içeren bir nesneyi sunucuya gönderir. Bu koordinatlar diğer tüm bağlı istemcilere yayınlanır. SignalR, JSON kullanarak bu nesneyi otomatik olarak serileştirir.

Uygulama nesneyi istemciye gönderir ShapeModel . Şeklin konumunu depolamak için üyeleri vardır. Sunucudaki nesnenin sürümü, hangi istemcinin verilerinin depolandığını izlemek için de bir üyeye sahiptir. Bu nesne, sunucunun istemci verilerini kendisine geri göndermesini engeller. Bu üye, uygulamanın verileri seri hale getirmesini ve istemciye geri göndermesini sağlamak için özniteliğini kullanır JsonIgnore .

Uygulama başlatıldığında hub'a eşleme

Ardından, uygulama başlatıldığında hub'a eşlemeyi ayarlarsınız. SignalR 2'de, bir OWIN başlangıç sınıfı eklemek eşlemeyi oluşturur.

  1. Çözüm Gezgini'de projeye sağ tıklayın ve Yeni Öğe Ekle'yi>seçin.

  2. Yeni Öğe Ekle - MoveShapeDemo bölümünde Yüklü>Visual C#>Web'i ve ardından OWIN Başlangıç Sınıfı'ni seçin.

  3. Sınıfa Başlangıç adını verin ve Tamam'ı seçin.

  4. Startup.cs dosyasındaki varsayılan kodu şu kodla değiştirin:

    using Microsoft.Owin;
    using Owin;
    
    [assembly: OwinStartup(typeof(MoveShapeDemo.Startup))]
    namespace MoveShapeDemo
    {
        public class Startup
        {
            public void Configuration(IAppBuilder app)
            {
                // Any connection or hub wire up and configuration should go here
                app.MapSignalR();
            }
        }
    }
    

Uygulama yöntemini yürüttüğünde OWIN başlangıç sınıfı çağrır MapSignalR Configuration . Uygulama, derleme özniteliğini kullanarak sınıfını OWIN'in başlangıç işlemine OwinStartup ekler.

İstemciyi ekleme

İstemci için HTML sayfasını ekleyin.

  1. Çözüm Gezgini'da projeye sağ tıklayın ve HTML Sayfası Ekle'yi>seçin.

  2. Sayfayı Varsayılan olarak adlandırın ve Tamam'ı seçin.

  3. Çözüm Gezgini'da Default.html sağ tıklayın ve Başlangıç Sayfası Olarak Ayarla'yı seçin.

  4. Default.html dosyasındaki varsayılan kodu şu kodla değiş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.10.2.min.js"></script>
    <script src="Scripts/jquery-ui-1.10.4.min.js"></script>
    <script src="Scripts/jquery.signalR-2.1.0.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>
    
  5. Çözüm Gezgini'da Betikler'i genişletin.

    jQuery ve SignalR için betik kitaplıkları projede görünür.

    Önemli

    Paket yöneticisi SignalR betiklerinin daha sonraki bir sürümünü yükler.

  6. Kod bloğundaki betik başvurularını, projedeki betik dosyalarının sürümlerine karşılık gelen şekilde güncelleştirin.

Bu HTML ve JavaScript kodu adlı shapebir kırmızı div oluşturur. jQuery kitaplığını kullanarak şeklin sürükleme davranışını etkinleştirir ve şeklin drag konumunu sunucuya göndermek için olayını kullanır.

Uygulamayı çalıştırma

Uygulamayı çalıştırarak çalışmasını sağlayabilirsiniz. Şekli tarayıcı penceresinin çevresinde sürüklediğinizde, şekil diğer tarayıcılarda da hareket eder.

  1. Araç çubuğunda Betik Hata Ayıklama'yı açın ve uygulamayı Hata Ayıklama modunda çalıştırmak için yürüt düğmesini seçin.

    Kullanıcının hata ayıklama modunu açmasının ve yürüt'ün seçilmesinin ekran görüntüsü.

    Sağ üst köşede kırmızı şekilli bir tarayıcı penceresi açılır.

  2. Sayfanın URL'sini kopyalayın.

  3. Başka bir tarayıcı açın ve URL'yi adres çubuğuna yapıştırın.

  4. Şekli tarayıcı pencerelerinden birinde sürükleyin. Diğer tarayıcı penceresindeki şekil aşağıdaki gibidir.

Uygulama bu yöntemi kullanarak çalışır ancak önerilen bir programlama modeli değildir. Gönderilen ileti sayısının üst sınırı yoktur. Sonuç olarak, istemciler ve sunucu iletilere boğulmuş olur ve performans düşer. Ayrıca, uygulama istemcide kopuk bir animasyon görüntüler. Bu sarsıntılı animasyon, şeklin her yöntem tarafından anında hareket ettiği için gerçekleşir. Şeklin her yeni konuma sorunsuz bir şekilde taşınması daha iyidir. Ardından, bu sorunları nasıl çözeceğinizi öğreneceksiniz.

İstemci döngüsünü ekleme

Her fare taşıma olayında şeklin konumunun gönderilmesi gereksiz miktarda ağ trafiği oluşturur. Uygulamanın istemciden gelen iletileri kısıtlaması gerekir.

Sunucuya sabit bir hızda yeni konum bilgileri gönderen bir döngü ayarlamak için javascript setInterval işlevini kullanın. Bu döngü, "oyun döngüsünün" temel bir gösterimidir. Bu, bir oyunun tüm işlevlerini yönlendiren, sürekli olarak adlandırılan bir işlevdir.

  1. Default.html dosyasındaki istemci kodunu şu kodla değiş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.10.2.min.js"></script>
    <script src="Scripts/jquery-ui-1.10.4.min.js"></script>
    <script src="Scripts/jquery.signalR-2.1.0.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>
    

    Önemli

    Betik başvurularını yeniden değiştirmeniz gerekir. Projedeki betiklerin sürümleriyle eşleşmesi gerekir.

    Bu yeni kod işlevi ekler updateServerModel . Sabit bir frekansta çağrılır. bayrağı gönderilecek yeni konum verileri olduğunu gösterdiğinde moved işlev konum verilerini sunucuya gönderir.

  2. Uygulamayı başlatmak için yürüt düğmesini seçin

  3. Sayfanın URL'sini kopyalayın.

  4. Başka bir tarayıcı açın ve URL'yi adres çubuğuna yapıştırın.

  5. Şekli tarayıcı pencerelerinden birinde sürükleyin. Diğer tarayıcı penceresindeki şekil aşağıdaki gibidir.

Uygulama sunucuya gönderilen iletilerin sayısını kısıtladığından, animasyon ilk başta 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ıkları sıklıkta çıkar. Bu ağ trafiği, istemcide gördüğümüze benzer bir sorun sunar.

Uygulama, gerektiğinden daha sık ileti gönderebilir. Bunun sonucunda bağlantı sular altında olabilir. Bu bölümde, giden iletilerin hızını azaltan bir zamanlayıcı eklemek için sunucunun nasıl güncelleştirildiği açıklanır.

  1. öğesinin içeriğini MoveShapeHub.cs şu kodla değiştirin:

    using System;
    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; }
        }
        
    }
    
  2. Uygulamayı başlatmak için yürüt düğmesini seçin.

  3. Sayfanın URL'sini kopyalayın.

  4. Başka bir tarayıcı açın ve URL'yi adres çubuğuna yapıştırın.

  5. Şekli tarayıcı pencerelerinden birinde sürükleyin.

Bu kod, sınıfını eklemek için istemciyi genişletir Broadcaster . Yeni sınıf, .NET framework'ten sınıfını Timer kullanarak giden iletileri kısıtlar.

Hub'ın kendisinin geçici olduğunu öğrenmek iyi bir şey. Her ihtiyaç duyulduğu zaman oluşturulur. Böylece uygulama tekil olarak öğesini Broadcaster oluşturur. 'nin oluşturulmasını gerekene kadar ertelemek Broadcasteriçin gecikmeli başlatmayı kullanır. Bu, uygulamanın zamanlayıcıyı başlatmadan önce ilk hub örneğini tamamen oluşturmasını garanti eder.

İstemcilerin UpdateShape işlevine yapılan çağrı daha sonra hub'ın UpdateModel yönteminden taşınır. Artık uygulama gelen iletileri aldığında hemen çağrılmaz. Bunun yerine uygulama, iletileri istemcilere saniyede 25 çağrı hızında gönderir. İşlem, sınıfın _broadcastLoop içinden Broadcaster zamanlayıcı tarafından yönetilir.

Son olarak, istemci yöntemini doğrudan hub'dan çağırmak yerine sınıfın Broadcaster şu anda işletim _hubContext hub'ına bir başvuru alması gerekir. ile başvuru alır GlobalHost.

Düz animasyon ekleme

Uygulama neredeyse tamamlandı, ancak bir iyileştirme daha yapabiliriz. Uygulama, sunucu iletilerine yanıt olarak şekli istemcide taşır. Şeklin konumunu sunucu tarafından verilen yeni konuma ayarlamak yerine JQuery UI kitaplığının animate işlevini kullanın. Şekli geçerli ve yeni konumu arasında sorunsuzca taşıyabilir.

  1. İstemcinin updateShape Default.html dosyasındaki yöntemini 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.10.2.min.js"></script>
    <script src="Scripts/jquery-ui-1.10.4.min.js"></script>
    <script src="Scripts/jquery.signalR-2.1.0.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>
    
  2. Uygulamayı başlatmak için yürüt düğmesini seçin.

  3. Sayfanın URL'sini kopyalayın.

  4. Başka bir tarayıcı açın ve URL'yi adres çubuğuna yapıştırın.

  5. Şekli tarayıcı pencerelerinden birinde sürükleyin.

Şeklin diğer penceredeki hareketi daha az sarsıntılı görünür. Uygulama, gelen ileti başına bir kez ayarlamak yerine zaman içindeki hareketini aramstırıyor.

Bu kod şekli eski konumdan yenisine taşır. Sunucu, animasyon aralığı boyunca şeklin konumunu verir. Bu durumda, bu 100 milisaniyedir. Uygulama, yeni animasyon başlamadan önce şekilde çalışan önceki animasyonları temizler.

Kodu alma

Tamamlanan Projeyi İndir

Ek kaynaklar

SignalR hakkında daha fazla bilgi için aşağıdaki kaynaklara bakın:

Sonraki adımlar

Bu öğreticide şunları yaptınız:

  • Projeyi ayarlama
  • Temel uygulama oluşturuldu
  • Uygulama başlatıldığında hub'a eşlendi
  • İstemci eklendi
  • Uygulamayı çalıştır
  • İstemci döngüsü eklendi
  • Sunucu döngüsü eklendi
  • Kesintisiz animasyon eklendi

Sunucu yayını işlevselliği sağlamak için ASP.NET SignalR 2 kullanan bir web uygulaması oluşturmayı öğrenmek için sonraki makaleye ilerleyin.