Partager via


Tutoriel : Créer une application en temps réel haute fréquence avec SignalR 2

Ce tutoriel montre comment créer une application web qui utilise ASP.NET SignalR 2 pour fournir des fonctionnalités de messagerie à haute fréquence. Dans ce cas, la « messagerie à haute fréquence » signifie que le serveur envoie des mises à jour à un débit fixe. Vous envoyez jusqu’à 10 messages par seconde.

L’application que vous créez affiche une forme que les utilisateurs peuvent faire glisser. Le serveur met à jour la position de la forme dans tous les navigateurs connectés pour qu’elle corresponde à la position de la forme déplacée à l’aide de mises à jour chronologiques.

Les concepts introduits dans ce didacticiel ont des applications dans les jeux en temps réel et d’autres applications de simulation.

Dans ce tutoriel, vous allez :

  • Configuration du projet
  • Créer l’application de base
  • Mapper au hub au démarrage de l’application
  • Ajouter le client
  • Exécuter l’application
  • Ajouter la boucle cliente
  • Ajouter la boucle du serveur
  • Ajouter une animation fluide

Avertissement

Cette documentation ne concerne pas la dernière version de SignalR. Examinez ASP.NET Core SignalR.

Prérequis

Configuration du projet

Dans cette section, vous allez créer le projet dans Visual Studio 2017.

Cette section montre comment utiliser Visual Studio 2017 pour créer une application web vide ASP.NET et ajouter les bibliothèques SignalR et jQuery.UI.

  1. Dans Visual Studio, créez une application web ASP.NET.

    Créer un site web

  2. Dans la fenêtre New ASP.NET Web Application - MoveShapeDemo , laissez Vide sélectionné et sélectionnez OK.

  3. Dans l’Explorateur de solutions, faites un clic droit sur le projet et sélectionnez Ajouter>Nouvel élément.

  4. Dans Ajouter un nouvel élément - MoveShapeDemo, sélectionnez Visual C#>Web>SignalR installé>, puis signalR Hub, classe (v2).

  5. Nommez la classe MoveShapeHub et ajoutez-la au projet.

    Cette étape crée le fichier de classe MoveShapeHub.cs . Simultanément, il ajoute un ensemble de fichiers de script et de références d’assembly qui prennent en charge SignalR au projet.

  6. Cliquez sur Outils>Gestionnaire de package NuGet>Console du Gestionnaire de package.

  7. Dans Gestionnaire de package Console, exécutez cette commande :

    Install-Package jQuery.UI.Combined
    

    La commande installe la bibliothèque d’interface utilisateur jQuery. Vous l’utilisez pour animer la forme.

  8. Dans Explorateur de solutions, développez le nœud Scripts.

    Références de bibliothèque de scripts

    Les bibliothèques de script pour jQuery, jQueryUI et SignalR sont visibles dans le projet.

Créer l’application de base

Dans cette section, vous allez créer une application de navigateur. L’application envoie l’emplacement de la forme au serveur pendant chaque événement de déplacement de la souris. Le serveur diffuse ces informations à tous les autres clients connectés en temps réel. Vous en apprendrez davantage sur cette application dans les sections ultérieures.

  1. Ouvrez le fichier MoveShapeHub.cs .

  2. Remplacez le code dans le fichier MoveShapeHub.cs par ce code :

    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. Enregistrez le fichier.

La MoveShapeHub classe est une implémentation d’un hub SignalR. Comme dans le didacticiel Getting Started with SignalR , le hub a une méthode que les clients appellent directement. Dans ce cas, le client envoie un objet avec les nouvelles coordonnées X et Y de la forme au serveur. Ces coordonnées sont diffusées sur tous les autres clients connectés. SignalR sérialise automatiquement cet objet à l’aide de JSON.

L’application envoie l’objet ShapeModel au client. Il a des membres pour stocker la position de la forme. La version de l’objet sur le serveur a également un membre pour suivre les données du client en cours de stockage. Cet objet empêche le serveur d’envoyer les données d’un client lui-même. Ce membre utilise l’attribut JsonIgnore pour empêcher l’application de sérialiser les données et de les renvoyer au client.

Mapper au hub au démarrage de l’application

Ensuite, vous configurez le mappage vers le hub au démarrage de l’application. Dans SignalR 2, l’ajout d’une classe de démarrage OWIN crée le mappage.

  1. Dans l’Explorateur de solutions, faites un clic droit sur le projet et sélectionnez Ajouter>Nouvel élément.

  2. Dans Ajouter un nouvel élément - MoveShapeDemo, sélectionnez Visual C#>Web installé>, puis sélectionnez Classe de démarrage OWIN.

  3. Nommez la classe Startup , puis sélectionnez OK.

  4. Remplacez le code par défaut dans le fichier Startup.cs par ce code :

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

La classe de démarrage OWIN appelle MapSignalR lorsque l’application exécute la Configuration méthode. L’application ajoute la classe au processus de démarrage d’OWIN à l’aide de l’attribut OwinStartup d’assembly.

Ajouter le client

Ajoutez la page HTML pour le client.

  1. Dans Explorateur de solutions, cliquez avec le bouton droit sur le projet, puis sélectionnez Ajouter>une page HTML.

  2. Nommez la page Par défaut , puis sélectionnez OK.

  3. Dans Explorateur de solutions, cliquez avec le bouton droit sur Default.html, puis sélectionnez Définir comme page de démarrage.

  4. Remplacez le code par défaut dans le fichier Default.html par ce code :

    <!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. Dans Explorateur de solutions, développez Scripts.

    Les bibliothèques de script pour jQuery et SignalR sont visibles dans le projet.

    Important

    Le gestionnaire de package installe une version ultérieure des scripts SignalR.

  6. Mettez à jour les références de script dans le bloc de code pour correspondre aux versions des fichiers de script dans le projet.

Ce code HTML et JavaScript crée un rouge div appelé shape. Il active le comportement de glissement de la forme à l’aide de la bibliothèque jQuery et utilise l’événement drag pour envoyer la position de la forme au serveur.

Exécuter l’application

Vous pouvez exécuter l’application pour qu’elle fonctionne. Lorsque vous faites glisser la forme autour d’une fenêtre de navigateur, la forme se déplace également dans les autres navigateurs.

  1. Dans la barre d’outils, activez le débogage de script, puis sélectionnez le bouton de lecture pour exécuter l’application en mode Débogage.

    Capture d’écran de l’activation du mode débogage par l’utilisateur et sélection de la lecture.

    Une fenêtre de navigateur s’ouvre avec la forme rouge dans le coin supérieur droit.

  2. Copiez l’URL de la page.

  3. Ouvrez un autre navigateur et collez l’URL dans la barre d’adresses.

  4. Faites glisser la forme dans l’une des fenêtres du navigateur. La forme dans l’autre fenêtre de navigateur suit.

Bien que les fonctions d’application utilisent cette méthode, il ne s’agit pas d’un modèle de programmation recommandé. Il n’existe aucune limite supérieure au nombre de messages envoyés. Par conséquent, les clients et le serveur sont submergés par les messages et les performances dégradent. En outre, l’application affiche une animation disjointe sur le client. Cette animation bizarre se produit parce que la forme se déplace instantanément par chaque méthode. Il est préférable que la forme se déplace en douceur vers chaque nouvel emplacement. Ensuite, vous allez apprendre à résoudre ces problèmes.

Ajouter la boucle cliente

L’envoi de l’emplacement de la forme sur chaque événement de déplacement de souris crée une quantité inutile de trafic réseau. L’application doit limiter les messages du client.

Utilisez la fonction javascript setInterval pour configurer une boucle qui envoie de nouvelles informations de position au serveur à un taux fixe. Cette boucle est une représentation de base d’une « boucle de jeu ». Il s’agit d’une fonction appelée à plusieurs reprises qui pilote toutes les fonctionnalités d’un jeu.

  1. Remplacez le code client dans le fichier Default.html par ce code :

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

    Vous devez remplacer à nouveau les références de script. Ils doivent correspondre aux versions des scripts dans le projet.

    Ce nouveau code ajoute la updateServerModel fonction. Elle est appelée sur une fréquence fixe. La fonction envoie les données de position au serveur chaque fois que l’indicateur moved indique qu’il existe de nouvelles données de position à envoyer.

  2. Sélectionnez le bouton lecture pour démarrer l’application

  3. Copiez l’URL de la page.

  4. Ouvrez un autre navigateur et collez l’URL dans la barre d’adresses.

  5. Faites glisser la forme dans l’une des fenêtres du navigateur. La forme dans l’autre fenêtre de navigateur suit.

Étant donné que l’application limite le nombre de messages envoyés au serveur, l’animation n’apparaît pas comme l’a fait au préalable.

Ajouter la boucle du serveur

Dans l’application actuelle, les messages envoyés du serveur au client sortent aussi souvent qu’ils sont reçus. Ce trafic réseau présente un problème similaire que nous voyons sur le client.

L’application peut envoyer des messages plus souvent qu’ils ne sont nécessaires. La connexion peut être inondée en conséquence. Cette section explique comment mettre à jour le serveur pour ajouter un minuteur qui limite le taux des messages sortants.

  1. Remplacez le contenu de MoveShapeHub.cs par ce code :

    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. Sélectionnez le bouton de lecture pour démarrer l’application.

  3. Copiez l’URL de la page.

  4. Ouvrez un autre navigateur et collez l’URL dans la barre d’adresses.

  5. Faites glisser la forme dans l’une des fenêtres du navigateur.

Ce code développe le client pour ajouter la Broadcaster classe. La nouvelle classe limite les messages sortants à l’aide de la Timer classe du .NET Framework.

Il est bon d’apprendre que le hub lui-même est transitoire. Il est créé chaque fois qu’il est nécessaire. Ainsi, l’application crée le Broadcaster singleton. Il utilise l’initialisation différée pour différer la création de l’objet Broadcasterjusqu’à ce qu’elle soit nécessaire. Cela garantit que l’application crée complètement la première instance du hub avant de démarrer le minuteur.

L’appel à la fonction des UpdateShape clients est ensuite déplacé hors de la méthode du UpdateModel hub. Elle n’est plus appelée immédiatement chaque fois que l’application reçoit des messages entrants. Au lieu de cela, l’application envoie les messages aux clients à un taux de 25 appels par seconde. Le processus est géré par le _broadcastLoop minuteur à partir de la Broadcaster classe.

Enfin, au lieu d’appeler directement la méthode cliente à partir du hub, la Broadcaster classe doit obtenir une référence au hub en cours d’exploitation _hubContext . Il obtient la référence avec le GlobalHost.

Ajouter une animation fluide

L’application est presque terminée, mais nous pourrions apporter une autre amélioration. L’application déplace la forme sur le client en réponse aux messages serveur. Au lieu de définir la position de la forme sur le nouvel emplacement donné par le serveur, utilisez la fonction de animate la bibliothèque d’interface utilisateur JQuery. Il peut déplacer la forme en douceur entre sa position actuelle et nouvelle.

  1. Mettez à jour la méthode du updateShape client dans le fichier Default.html pour ressembler au code mis en surbrillance :

    <!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. Sélectionnez le bouton de lecture pour démarrer l’application.

  3. Copiez l’URL de la page.

  4. Ouvrez un autre navigateur et collez l’URL dans la barre d’adresses.

  5. Faites glisser la forme dans l’une des fenêtres du navigateur.

Le mouvement de la forme dans l’autre fenêtre apparaît moins bizarre. L’application interpole son déplacement au fil du temps plutôt que d’être définie une seule fois par message entrant.

Ce code déplace la forme de l’ancien emplacement vers le nouvel emplacement. Le serveur donne la position de la forme au cours de l’intervalle d’animation. Dans ce cas, il s’agit de 100 millisecondes. L’application efface toute animation précédente s’exécutant sur la forme avant le démarrage de la nouvelle animation.

Obtenir le code

Télécharger le projet terminé

Ressources supplémentaires

Pour plus d’informations sur SignalR, consultez les ressources suivantes :

Étapes suivantes

Dans ce tutoriel, vous allez :

  • Configuration du projet
  • Création de l’application de base
  • Mappé au hub au démarrage de l’application
  • Ajout du client
  • Exécution de l’application
  • Ajout de la boucle cliente
  • Ajout de la boucle du serveur
  • Ajout d’une animation fluide

Passez à l’article suivant pour apprendre à créer une application web qui utilise ASP.NET SignalR 2 pour fournir des fonctionnalités de diffusion de serveur.