Loupe

Développement d’applications web et mobiles qui consomment des données en temps réel - partie 3

Ce billet est le troisième de la série d’articles dédiée au développement d’applications web et mobiles qui utilisent des données en temps réel, co-écrite avec Stéphane Goudeau. Si vous n’avez pas eu l’occasion de lire les deux billets précédents, je vous invite à le faire en suivant les liens dans la table des matières ci-dessous :

Introduction

Dans son dernier article, Stéphane nous a présenté le Framework SignalR de Microsoft dans sa globalité, son fonctionnement et sa mise en place côté serveur, dans le but de créer un hub dans un site web ASP.NET MVC hébergé dans Microsoft Azure.

Aujourd’hui, nous allons nous intéresser plus en détails au client JavaScript fourni par Microsoft et qui permet d’intéragir avec un hub, depuis une page web. Pour mémoire, voilà la configuration serveur que Stéphane proposait dans son article :

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        app.Map("/signalr", map =>
        {
            map.UseCors(CorsOptions.AllowAll);

            hubConfiguration.EnableDetailedErrors = true;

            map.RunSignalR(hubConfiguration);
        });

        GlobalHost.TraceManager.Switch.Level = SourceLevels.Information;
    }
}

Cette configuration est très importante puisqu’elle nous apporte deux informations essentielles pour la communication depuis un client JavaScript :

  • L’URL à laquelle les hubs SignalR peuvent être contactés sur le serveur (pour la génération automatique de proxy) : /signalr
  • Le fait que le serveur supporte les accès en cross-origin (ici très permissif, puisqu’autorisant toutes les origines) : cela nous assure que notre application web pourra communiquer avec le hub, quelque soit le domaine qui distribue l’application web cliente.

La librairie SignalR JavaScript

Pour récupérer le client JavaScript dans votre projet, le plus simple est d’utiliser la console de packages NuGet dans Visual Studio, et de rechercher “SignalR” :

image

Parmi la liste des résultats retournés, vous devriez trouver un package Microsoft ASPNET SignalR JavaScript Client. Vous pouvez alors l’installer dans votre application.

Deux fichiers seront alors ajoutés au dossier Scripts de votre projet (la version debug et la version minifiée):

image

Si vous travaillez avec les bundles ASP.NET, vous pouvez rajouter une entrée pour SignalR lors de la configuration des bundles :

bundles.Add(new ScriptBundle("~/bundles/signalr").Include(
            "~/Scripts/jquery.signalR-{version}.js"));

Puis effectuer le rendu de votre bundle dans la page ou vous souhaitez vous connecter avec un hub SignalR :

@Scripts.Render("~/bundles/signalr")

Si vous n’utilisez pas les bundles, il suffit d’importer le script de manière plus classique :

<script src="~/Scripts/jquery.signalR-2.1.0.min.js"></script>

Ceci étant fait, vous êtes prêts à communiquer avec le hub ! Let’s go Smile

Etablissement de la connexion avec un hub SignalR, en JavaScript

Comme je le disais en début d’article, Microsoft a choisi de proposer un client SignalR basé sur jQuery. Dès lors que vous avez importé le script dans votre page, vous pourrez retrouver un objet “connection” directement sur $. C’est le point d’entrée qui va vous permettre de travailler avec SignalR côté client.

Dans notre exemple, le hub est hébergé à l’adresse : http://iotsignalrhub.azurewebsites.net/signalr.

En tout premier lieu, il s’agit de récupérer un proxy vers le hub à contacter. Aussi étonnant que cela puisse paraître, il est nécessaire que cette étape soit réalisée avant même la connexion avec le serveur soit établie:

var iotHub = $.connection.iotHub;

Le nom “iotHub” n’est pas sorti de nulle part, il s’agit du nom que Stéphane a donné au hub côté serveur :

image

Il est ensuite nécessaire de configurer le hub pour lui indiquer l’URL à laquelle se connecter :

var iotHub = $.connection.iotHub;

if(!iotHub){
    console.log("signalr n'est pas disponible");
}

var url = 'http://iotsignalrhub.azurewebsites.net/signalr';

//on renseigne l'url
iotHub.connection.url = url;

Nous allons maintenant pouvoir nous abonner aux différents événements du cycle de vie de la connexion SignalR. Pour cela, l’objet $.connection expose une fonction stateChanged qui permet de récupérer l’état de la connexion :

$.connection.hub.stateChanged(function (change) {
    if (change.newState === $.signalR.connectionState.connected) {
        console.log("connecté");
    } else if (change.newState === $.signalR.connectionState.reconnecting) {
        console.log("reconnexion en cours...");
    } else if (change.newState === $.signalR.connectionState.disconnected) {
        console.log("déconnecté");
    } else if (change.newState === $.signalR.connectionState.connecting) {
        console.log("connexion en cours...");
    }

});

La dernière étape avant de démarrer la connexion consiste à créer les handlers aux fonctions disponibles sur le proxy. Ces fonctions sont étroitement liées aux méthodes que vous appelez sur le hub, côté serveur. Dans notre cas, nous appelons une méthode “newMeasureAvailable” sur tous les clients connectés lors que le hub SignalR reçoit une mesure, côté serveur :

image

De manière assez logique, nous allons donc déclarer le prototype de cette fonction sur le client du hub iotHub, côté JavaScript :

iotHub.client.newMeasureAvailable = function(measure){
    console.log("nouvelle mesure disponible");
    console.log("température : " + measure.temperature);
    console.log("humidité : " + measure.humidity);
};

Notre client SignalR est maintenant configuré correctement. Il ne reste qu’à démarrer la connexion, à l’aide de la function start sur l’objet $.connection.hub :

$.connection.hub.start().done(function () {
    console.log("connexion ok");
});

Dès qu’une nouvelle mesure sera disponible côté serveur, elle sera automatiquement envoyées à votre client SignalR qui pourra la traiter côté JavaScript.

Ce qui est très intéressant ici, c’est que vous n’avez pas à vous préoccuper de la sérialisation / déséralisation des données qui transitent entre le hub et le client JS, SignalR le fait pour vous, et vous donne directement des objets JavaScript en paramètres des fonctions de votre hub proxy.

Négociation et connexion

Comme Stéphane l’indique dans son article, la connexion au hub se fait en réalité en deux étapes : une étape de négociation avec le serveur pour que client et serveur décident du mode de communication (WebSocket, long polling, sent events, forever frame…). Ce choix va se faire surtout en fonction du navigateur web que vous utilisez. Sur les navigateurs modernes, la nogociation aboutit la plupart du temps à l’ouverture d’un WebSocket, qui est le mode de transport le plus adapté à du real time dans une application web. Sur Internet Explorer 8, se sera du Long Polling : ce ne sera pas une connexion persistante qui sera établie entre le client et le serveur, mais des requêtes en continue du client vers le serveur.

Vous pouvez analyser les trames réseaux de votre navigateur pour visualiser cette étape de négociation :

image

Le résultat de cette requête indique au client JavaScript comment établir la connexion au hub :

{ 
    "Url": "/signalr", 
    "ConnectionToken": "AreYouTokenToMe?", 
    "ConnectionId": "284dc2ed-5dbc-432e-8700-177c23a517b3", 
    "KeepAliveTimeout": 20.0, 
    "DisconnectTimeout": 30.0, 
    "TryWebSockets": true, 
    "ProtocolVersion": "1.4", 
    "TransportConnectTimeout": 5.0, 
    "LongPollDelay": 0.0 
}

Outre le token et l’id de connexion, on retrouve bien des informations relatives au protocol à utiliser. Ici, on voit que le serveur à répondu au client d’utiliser des WebSockets pour se connecter.

La deuxième requête envoyée correspond à la connexion :

image

Ici, le client fait un start en utilisant le protocol WebSockets.

Au passage, si vous regardez dans la console, vous verrez les différents évènements relatifs au “statechanged” de la connexion :

image

Conclusion

Dans cet article, nous avons pu voir comment établir une connexion avec un hub SignalR depuis JavaScript en utilisant le client jQuery proposé par Microsoft. Les étapes importantes pour la mise en place de la communication sont résumées dans la liste ci-dessous :

  1. Référencement du script SignalR client
  2. Récupération du hub sur l’objet $.connection
  3. Configuration du proxy et des handlers
  4. Démarrage de la connexion, qui donne lieu à la négociation du transport et au start !

Dans le prochain article, je vous parlerai de l’utilisation du SDK .NET Client pour SignalR, qui comme sont nom l’indique permet de se connecter à un hub SignalR, mais depuis une application .NET !

A bientôt Winking smile

Julien

Ces billets pourraient aussi vous intéresser

Vous nous direz ?!

Commentaires

comments powered by Disqus