Samouczek: Tworzenie aplikacji w czasie rzeczywistym o wysokiej częstotliwości z sygnałem 2

W tym samouczku pokazano, jak utworzyć aplikację sieci Web korzystającą z ASP.NET sygnalizującego 2, aby zapewnić funkcję obsługi komunikatów o wysokiej częstotliwości. W takim przypadku "Obsługa komunikatów o wysokiej częstotliwości" oznacza, że serwer wysyła aktualizacje ze stałą stawką. Wysyłasz do 10 wiadomości w drugim.

Utworzona aplikacja wyświetla kształt, który użytkownicy mogą przeciągać. Serwer aktualizuje położenie kształtu we wszystkich połączonych przeglądarkach, aby dopasować położenie przeciąganego kształtu przy użyciu aktualizacji z limitem czasu.

Koncepcje wprowadzone w tym samouczku zawierają aplikacje w czasie rzeczywistym oraz inne aplikacje symulacyjne.

W tym samouczku zostaną wykonane następujące czynności:

  • Konfigurowanie projektu
  • Tworzenie aplikacji podstawowej
  • Mapuj do centrum podczas uruchamiania aplikacji
  • Dodawanie klienta
  • Uruchamianie aplikacji
  • Dodaj pętlę klienta
  • Dodaj pętlę serwera
  • Dodaj gładką animację

Warning

Ta dokumentacja nie jest najnowsza dla najnowszej wersji usługi sygnalizującej. Zapoznaj się z tematem ASP.NET Core sygnalizujący.

Wymagania wstępne

  • Program Visual Studio 2017 z pakietem roboczym Tworzenie aplikacji na platformie ASP.NET i aplikacji internetowych.

Konfigurowanie projektu

W tej sekcji utworzysz projekt w programie Visual Studio 2017.

W tej sekcji pokazano, jak za pomocą programu Visual Studio 2017 utworzyć pustą aplikację sieci Web ASP.NET i dodać do niej elementy sygnalizujące i jQuery. UI.

  1. W programie Visual Studio Utwórz aplikację sieci Web ASP.NET.

    Tworzenie sieci Web

  2. W oknie Nowa aplikacja sieci Web ASP.NET — MoveShapeDemo , pozostaw puste zaznaczone i wybierz przycisk OK.

  3. W Eksplorator rozwiązańkliknij prawym przyciskiem myszy projekt, a następnie wybierz pozycję Dodaj > nowy element.

  4. W obszarze Dodaj nowy element — MoveShapeDemowybierz pozycję zainstalowane > Visual C# > sieci Web > sygnalizujący , a następnie wybierz pozycję Klasa centrum sygnałów (v2) .

  5. Nadaj klasie nazwę MoveShapeHub i Dodaj ją do projektu.

    Ten krok powoduje utworzenie pliku klasy MoveShapeHub.cs . Jednocześnie dodaje zestaw plików skryptów i odwołania do zestawów, które obsługują sygnalizujący do projektu.

  6. Wybierz kolejno pozycje narzędzia > menedżer pakietów NuGet > konsola Menedżera pakietów.

  7. W konsoli Menedżera pakietówUruchom następujące polecenie:

    Install-Package jQuery.UI.Combined
    

    Polecenie instaluje bibliotekę interfejsu użytkownika jQuery. Służy do animowania kształtu.

  8. W Eksplorator rozwiązańrozwiń węzeł skrypty.

    Odwołania do biblioteki skryptów

    Biblioteki skryptów dla jQuery, jQueryUI i sygnalizujący są widoczne w projekcie.

Tworzenie aplikacji podstawowej

W tej sekcji utworzysz aplikację przeglądarki. Aplikacja wysyła lokalizację kształtu do serwera podczas każdego zdarzenia przenoszenia myszy. Serwer emituje te informacje do wszystkich innych podłączonych klientów w czasie rzeczywistym. Więcej informacji na temat tej aplikacji znajdziesz w kolejnych sekcjach.

  1. Otwórz plik MoveShapeHub.cs .

  2. Zastąp kod w pliku MoveShapeHub.cs tym kodem:

    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. Zapisz plik.

Klasa MoveShapeHub jest implementacją centrum sygnałów. Podobnie jak w przypadku wprowadzenie z samouczkiem sygnalizującym , koncentrator ma metodę, którą klienci bezpośrednio wywołują. W takim przypadku klient wysyła obiekt z nowymi współrzędnymi X i Y kształtu do serwera. Te współrzędne są wysyłane do wszystkich innych podłączonych klientów. Program sygnalizujący automatycznie serializować ten obiekt przy użyciu formatu JSON.

Aplikacja wysyła do klienta obiekt ShapeModel. Ma elementy członkowskie do przechowywania pozycji kształtu. Wersja obiektu na serwerze ma również element członkowski służący do śledzenia, które dane klienta są przechowywane. Ten obiekt uniemożliwia serwerowi wysyłanie danych klienta z powrotem do samego siebie. Ten element członkowski używa atrybutu JsonIgnore, aby uniemożliwić aplikacji Serializowanie danych i wysłanie jej z powrotem do klienta.

Mapuj do centrum podczas uruchamiania aplikacji

Następnie należy skonfigurować mapowanie do centrum podczas uruchamiania aplikacji. W sygnalizacji 2 dodanie klasy uruchomieniowej OWIN powoduje utworzenie mapowania.

  1. W Eksplorator rozwiązańkliknij prawym przyciskiem myszy projekt, a następnie wybierz pozycję Dodaj > nowy element.

  2. W obszarze Dodaj nowy element — MoveShapeDemo wybierz pozycję zainstalowane > C# Visual > Web , a następnie wybierz pozycję Owin klasy startowej.

  3. Nazwij klasę uruchamiania i wybierz przycisk OK.

  4. Zastąp domyślny kod w pliku Startup.cs tym kodem:

    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();
            }
        }
    }
    

Klasa uruchomieniowa OWIN wywołuje MapSignalR, gdy aplikacja wykonuje Configuration metodę. Aplikacja dodaje klasę do procesu uruchamiania OWIN przy użyciu atrybutu zestawu OwinStartup.

Dodawanie klienta

Dodaj stronę HTML dla klienta.

  1. W Eksplorator rozwiązańkliknij prawym przyciskiem myszy projekt i wybierz polecenie Dodaj > stronę HTML.

  2. Nadaj nazwę stronie domyślne i wybierz przycisk OK.

  3. W Eksplorator rozwiązańkliknij prawym przyciskiem myszy pozycję default. html i wybierz pozycję Ustaw jako stronę startową.

  4. Zastąp domyślny kod w pliku default. html tym kodem:

    <!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. W Eksplorator rozwiązańrozwiń węzeł skrypty.

    Biblioteki skryptów dla jQuery i sygnalizujących są widoczne w projekcie.

    Important

    Menedżer pakietów instaluje nowszą wersję skryptów sygnalizujących.

  6. Zaktualizuj odwołania do skryptu w bloku kodu, aby odpowiadały wersji plików skryptów w projekcie.

Ten kod HTML i JavaScript tworzy czerwoną div o nazwie shape. Umożliwia ona zachowanie przeciągnięcia kształtu przy użyciu biblioteki jQuery i użycie zdarzenia drag do wysłania położenia kształtu do serwera.

Uruchamianie aplikacji

Możesz uruchomić aplikację, aby se'e jej działanie. Po przeciągnięciu kształtu wokół okna przeglądarki, kształt jest również przenoszony w innych przeglądarkach.

  1. Na pasku narzędzi Włącz debugowanie skryptów , a następnie wybierz przycisk Odtwórz, aby uruchomić aplikację w trybie debugowania.

    Zrzut ekranu przedstawiający Włączanie trybu debugowania przez użytkownika i wybieranie opcji Odtwórz.

    Zostanie otwarte okno przeglądarki z czerwonym kształtem w prawym górnym rogu.

  2. Skopiuj adres URL strony.

  3. Otwórz kolejną przeglądarkę i wklej adres URL na pasku adresu.

  4. Przeciągnij kształt w jednym z okien przeglądarki. Poniższy kształt w drugim oknie przeglądarki.

Gdy aplikacja korzysta z tej metody, nie jest to zalecany model programowania. Nie ma górnego limitu liczby wysyłanych komunikatów. W związku z tym klienci i serwery są przeciążone komunikatami i obniżeniem wydajności. Ponadto aplikacja wyświetla rozłączne animacje na kliencie. Ta animacja Jerky ma miejsce, ponieważ kształt jest przesuwany natychmiast przez każdą metodę. Lepiej, jeśli kształt zostanie bezproblemowo przeniesiony do każdej nowej lokalizacji. Następnie dowiesz się, jak rozwiązać te problemy.

Dodaj pętlę klienta

Wysyłanie lokalizacji kształtu przy każdym zdarzeniu przenoszenia myszy powoduje utworzenie niepotrzebnego ruchu sieciowego. Aplikacja musi ograniczyć komunikaty z klienta.

Użyj funkcji setInterval JavaScript, aby skonfigurować pętlę, która wysyła nowe informacje o pozycji do serwera ze stałą stawką. Ta pętla to podstawowa reprezentacja "pętli gry". Jest to wielokrotnie wywoływana funkcja, która steruje wszystkimi funkcjami gry.

  1. Zastąp kod klienta w pliku default. html tym kodem:

    <!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>
    

    Important

    Należy ponownie zastąpić odwołania do skryptu. Muszą one być zgodne z wersjami skryptów w projekcie.

    Ten nowy kod dodaje funkcję updateServerModel. Jest wywoływana z ustaloną częstotliwością. Funkcja wysyła dane położenia do serwera za każdym razem, gdy flaga moved wskazuje, że nowe dane położenia są wysyłane.

  2. Wybierz przycisk Odtwórz, aby uruchomić aplikację

  3. Skopiuj adres URL strony.

  4. Otwórz kolejną przeglądarkę i wklej adres URL na pasku adresu.

  5. Przeciągnij kształt w jednym z okien przeglądarki. Poniższy kształt w drugim oknie przeglądarki.

Ponieważ aplikacja ogranicza liczbę komunikatów wysyłanych do serwera, animacja nie będzie wyświetlana jako gładka.

Dodaj pętlę serwera

W bieżącej aplikacji komunikaty wysyłane z serwera do klienta są wykonywane tak często, jak są odbierane. Ten ruch sieciowy przedstawia podobny problem, który jest widoczny na kliencie.

Aplikacja może wysyłać komunikaty częściej niż jest to zbędne. Połączenie może zostać zalanie w wyniku. W tej sekcji opisano sposób aktualizowania serwera programu w celu dodania czasomierza, który ogranicza szybkość wychodzących komunikatów.

  1. Zastąp zawartość MoveShapeHub.cs tym kodem:

    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. Wybierz przycisk Odtwórz, aby uruchomić aplikację.

  3. Skopiuj adres URL strony.

  4. Otwórz kolejną przeglądarkę i wklej adres URL na pasku adresu.

  5. Przeciągnij kształt w jednym z okien przeglądarki.

Ten kod rozszerza klienta, aby dodać klasę Broadcaster. Nowa Klasa ogranicza komunikaty wychodzące przy użyciu klasy Timer z programu .NET Framework.

Warto dowiedzieć się, że sam koncentrator jest przejściowy. Jest on tworzony za każdym razem, gdy jest to konieczne. Aplikacja tworzy Broadcaster jako pojedynczą. Używa inicjalizacji z opóźnieniem, aby odroczyć tworzenie Broadcasterdo momentu, gdy jest to konieczne. Gwarantuje to, że aplikacja tworzy pierwsze wystąpienie centrum w całości przed rozpoczęciem czasomierza.

Wywołanie funkcji UpdateShape klientów zostanie następnie przeniesione z metody UpdateModel centrum. Nie jest już wywoływana natychmiast po każdym odebraniu wiadomości przychodzących przez aplikację. Zamiast tego aplikacja wysyła komunikaty do klientów z szybkością 25 wywołań na sekundę. Proces jest zarządzany przez _broadcastLoop Timer z poziomu klasy Broadcaster.

Na koniec zamiast wywoływania metody klienta bezpośrednio z poziomu centrum Klasa Broadcaster musi uzyskać odwołanie do centrum _hubContext operacyjnego. Pobiera odwołanie do GlobalHost.

Dodaj gładką animację

Aplikacja jest niemal zakończona, ale możemy wprowadzić jeszcze jedną poprawę. Aplikacja przenosi kształt na kliencie w odpowiedzi na komunikaty serwera. Zamiast ustawiania położenia kształtu do nowej lokalizacji wskazanej przez serwer, użyj funkcji animate biblioteki interfejsu użytkownika JQuery. Może bezproblemowo przenosić kształt między jego bieżącą i nową pozycją.

  1. Zaktualizuj metodę updateShape klienta w pliku default. html , aby wyglądać jak wyróżniony kod:

    <!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. Wybierz przycisk Odtwórz, aby uruchomić aplikację.

  3. Skopiuj adres URL strony.

  4. Otwórz kolejną przeglądarkę i wklej adres URL na pasku adresu.

  5. Przeciągnij kształt w jednym z okien przeglądarki.

Przenoszenie kształtu w drugim oknie jest mniej Jerky. Aplikacja interpoluje swój ruch w czasie, a nie ustawia raz na komunikat przychodzący.

Ten kod przenosi kształt ze starej lokalizacji do nowej. Serwer podaje pozycję kształtu w trakcie interwału animacji. W tym przypadku jest to 100 milisekund. Aplikacja czyści wszystkie poprzednie animacje uruchomione na kształcie przed rozpoczęciem nowej animacji.

Uzyskiwanie kodu

Pobierz ukończony projekt

Dodatkowe zasoby

Właśnie zdobyty model komunikacji jest przydatny do tworzenia gier online i innych symulacji, takich jak gra w ramach programu do tworzenia sygnałów.

Aby uzyskać więcej informacji o sygnalizacji, zobacz następujące zasoby:

Następne kroki

W tym samouczku zostaną wykonane następujące czynności:

  • Konfigurowanie projektu
  • Utworzono aplikację podstawową
  • Zamapowane do centrum podczas uruchamiania aplikacji
  • Dodano klienta
  • Uruchomiono aplikację
  • Dodano pętlę klienta
  • Dodano pętlę serwera
  • Dodano gładką animację

Przejdź do następnego artykułu, aby dowiedzieć się, jak utworzyć aplikację sieci Web, która korzysta z ASP.NET sygnalizującego 2, aby zapewnić funkcję emisji serwera.