IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Débuter avec .NET Remoting en VB.NET

Cet article vous propose de découvrir la technologie .NET Remoting à travers un tutoriel expliquant la réalisation d'un projet client/serveur complet. Le code proposé est en VB.NET. Voir la version C# ou Delphi.NET (Par Laurent Dardenne). Et après l'article : détente avec du sudoku.

N'hésitez pas à commenter cet article ! Commentez Donner une note à l´article (5)

Article lu   fois.

L'auteur

Profil ProSite personnel

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

I. Présentation

I-A. .NET Remoting, c'est quoi ?

.NET Remoting est une technologie permettant l'implémentation d'applications distribuées. Elle est comparable à RMI en Java.
Le principe général est d'exposer sur une partie serveur des objets accessibles par des clients distants.
Les objets ou leur référence pourront donc transiter via le réseau grâce au principe du marshalling (empaquetage). Les protocoles et formatages possibles sont paramétrables : TCP+Binaire ou Http+Soap par exemple. Par défaut, le framework .NET propose Tcp et Http, mais la technologie .NET Remoting permet à des éditeurs tiers de réaliser leurs propres implémentations et rend donc .NET Remoting potentiellement ouvert.

Voici un schéma simple qui résume le fonctionnement global de .NET Remoting :

Le proxy défini sur le schéma est une couche intermédiaire créée dynamiquement par le framework et qui se charge du routage des demandes du client vers le serveur sur le réseau et inversement de récupérer les réponses du serveur. Donc, lorsque vous réaliserez des appels distants, vous ne dialoguerez pas directement avec le serveur, mais avec le proxy.

Le marshalling et unmarshalling des données correspondent aux principes de transformation de données pour qu'elles puissent circuler sur un réseau selon un protocole et un format définis. Ces processus interviennent autant du côté du client que du côté du serveur dès qu'il y a réception ou envoi de données.
Nous reviendrons sur la notion de « MarshalByRefObject » plus tard dans l'article.

Le marshalling, c'est un peu comme lorsque vous mettez un objet dans un colis, vous le placez en un format qui permettra son transport. Le réseau étant ici la Poste ou un transporteur quelconque. Le fait de mettre l'objet dans le paquet, c'est du marshalling, le fait de déballer le paquet et d'en extraire l'objet est le unmarshalling.

De même, plus l'objet est gros et lourd, plus le timbre coûtera cher. Il en est de même avec un réseau où le coût en bande passante augmentera en même temps que le poids des données.

I-B. Objectif de l'article

Le but de cet article n'est pas d'entrer dans les détails et subtilités de la technologie .NET Remoting, mais de découvrir son fonctionnement de base par la pratique.

Pour comprendre concrètement le fonctionnement de .NET Remoting, nous allons réaliser trois projets VB.NET :

l'interface : elle contiendra la déclaration des méthodes de l'objet distribué ;
le serveur : il possèdera un objet contenant deux méthodes, une qui réalise l'addition de deux entiers et une autre qui incrémente simplement une variable ;
le client : il s'agira d'une application fenêtrée qui appellera à distance l'objet situé sur le serveur.

Nous testerons ensuite les projets et en observerons les comportements.

Si vous êtes perdu pendant le déroulement de ce tutoriel, voici la structure de la solution finale. Vous pourrez ainsi vous y référer en cas de besoin :

Image non disponible

II. L'interface

Pour que le client ait connaissance des méthodes distantes, une interface contenant leur déclaration doit être distribuée côté client et côté serveur. L'objet exposé sur le serveur devra implémenter cette interface.
Cette interface sera le seul élément commun entre le serveur et le client. Donc pour simplifier sa distribution, nous allons créer une dll.

Ouvrez Visual Studio .NET.
Créez une nouvelle solution vierge : « RemotingSolution ».
Ajoutez à la solution un nouveau projet VB.NET de type « Bibliothèque de classes », nomme- le : « RemotingInterfaces ».
Renommez le fichier Module1.vb en « IRemoteOperation.vb ».
Remplacez la classe Module1 dans le code par :

 
Sélectionnez
VB.NET
Public Interface IRemoteOperation

    Function Addition(ByVal a As Integer, ByVal b As Integer) As Integer
    Function Incrementation(ByVal valeur As Integer) As Integer

End Interface

Compilez le projet.

III. Le serveur

III-A. L'objet distribué

Ajoutez à la solution créée précédemment un nouveau projet VB.NET de type « Application Console », nommez-le « RemotingServeur ».
Ajoutez au projet une référence au projet « RemotingInterfaces ».
Ajouter un fichier « RemoteOperation.vb ».
Indiquez dans ce fichier le code suivant, il s'agit de l'objet distant :

 
Sélectionnez
VB.NET

Imports System



Public Class RemoteOperation

    Inherits MarshalByRefObject

    Implements RemotingInterfaces.IRemoteOperation



    Private nombre As Integer = 0 ' sera incrément par Incrementation()



    ' Indique que l'objet aura une durée de vie illimitée

    Public Overrides Function InitializeLifetimeService() As Object

        Return Nothing

    End Function



    ' Définition de Addition, cette méthode sera exposée

    Public Function Addition(ByVal a As Integer, ByVal b As Integer) _

        As Integer Implements RemotingInterfaces.IRemoteOperation.Addition

        Console.WriteLine(String.Format("Appel client sur Addition() : a={0}, b={1}", a, b))

        Return (a + b)

    End Function



    ' Définition de Incrementation, cette méthode sera exposée

    Public Function Incrementation(ByVal valeur As Integer) _

        As Integer Implements RemotingInterfaces.IRemoteOperation.Incrementation

        Console.WriteLine(String.Format("Appel client sur Incrementation() : valeur={0}", valeur))

        nombre = (nombre + valeur)

        Return nombre

    End Function

End Class

RemoteOperation sera ensuite directement exposé au client.

- Il implémente la classe MarshalByRefObject qui indique que le client ne contiendra qu'une référence de l'objet et non l'objet lui-même, une sorte de pointeur de fonction distant. Ce fonctionnement est à opposer à MarshalByValue où une copie complète d'un objet sérialisable est passée au client, mais nous ne l'utilisons pas ici.

- Les méthodes Addition() et Incrementation() sont aussi définies conformément à l'interface IRemoteOperation.

- InitializeLifetimeService est surchargée en retournant null. Sans cela, la durée de vie de l'objet serait par défaut : au premier appel : 5 min puis de 2 min à chaque appel. Elle est, dans notre cas, infinie.
La possibilité de durée de vie limitée peut être intéressante, mais, dans le cadre de ce tutoriel, il n'y a pas lieu d'en placer.

Pour plus de simplicité, le code d'addition et de multiplication est directement écrit dans les méthodes exposées. En général, il est préférable d'écrire des classes spécifiques à ces traitements et laisser les classes en front s'occuper uniquement des appels.

III-B. Configuration et lancement du serveur

Ajoutez une référence à « System.Runtime.Remoting ».
Renommez le fichier Module1.vb en « RemoteMain.vb ».
Placez-y le code suivant, il permet de démarrer le serveur et d'exposer notre objet :

 
Sélectionnez
VB.NET

Imports System

Imports System.Runtime.Remoting

Imports System.Runtime.Remoting.Channels

Imports System.Runtime.Remoting.Channels.Tcp



Class RemotingMain



    <STAThread()> _

    Public Shared Sub Main(ByVal args() As String)

        Try

            ' Création d'un nouveau canal d'écoute sur le port 1069

            Dim channel As TcpChannel = New TcpChannel(1069)

            ' Enregistrement du canal

            ChannelServices.RegisterChannel(channel)

            ' Démarrage de l'écoute en exposant l'objet en Singleton

            RemotingConfiguration.RegisterWellKnownServiceType(GetType(RemoteOperation), _

                                "RemoteOperation", WellKnownObjectMode.Singleton)

            Console.WriteLine("Le serveur a démarré avec succès")

            Console.ReadLine()

        Catch

            Console.WriteLine("Erreur lors du démarrage du serveur")

            Console.ReadLine()

        End Try

    End Sub

End Class

- Ici, nous créons un nouveau Channel (canal) de type Tcp. Des channels d'autres types pourraient être utilisés comme HttpChannel ou des développements non standards comme IIOPChannel. TcpChannel a l'avantage ici d'être plus rapide que HttpChannel puisque les données transitent en binaire.

- Ce channel est ensuite enregistré sur le serveur pour être trouvé par le client.

- Puis l'écoute est lancée avec l'objet RemoteOperation exposé en mode Singleton.

Deux types de modes d'activation côté serveur peuvent être accordés à un objet distant avec la technologie .NET Remoting :
Singleton : un seul objet est partagé entre les clients et les appels pendant une durée de vie fixée. Lorsque la durée de vie est expirée, l'objet est réinstancié ;
SingleCall : à chaque appel, le serveur crée une nouvelle instance de l'objet qui est détruit après chaque utilisation.

Sachez également qu'il est possible, en passant par une activation côté client de l'objet, que le serveur crée une instance de l'objet pour chaque client.

Remarque : nous utilisons RegisterWellKnownServiceType(). Or, il existe une autre méthode de la classe RemotingConfiguration : Configure(). Cette méthode permet de charger un fichier XML contenant toutes les informations de configuration du remoting serveur. Cette solution peut s'avérer très pratique même si nous ne l'avons pas utilisée ici.

Une fois le code ajouté, compilez le projet « RemotingServeur ». Si une erreur se produit concernant la méthode « Sub Main » introuvable, double-cliquez sur la ligne signifiant l'erreur et redéfinissez la classe de démarrage (Module1 -> RemoteMain).

Pour simplifier et ne pas multiplier les classes, nous avons mis le code de configuration et de démarrage du serveur dans la méthode Main(). Il est cependant préférable de réaliser une classe dédiée cette tâche.

IV. Le client

IV-A. Interface graphique

Ajoutez à la solution créée précédemment un nouveau projet VB.NET de type « Windows Form », nommez-le « RemotingClient »
Placez sur l'éditeur graphique de Form1, les contrôles comme ceci, en respectant les noms :

Image non disponible

IV-B. Récupération de la référence à l'objet distant

Ajoutez une référence au projet « RemotingInterfaces ».
Ajoutez une référence à « System.Runtime.Remoting ».
Ajoutez les déclarations suivantes dans le code de la Form :

 
Sélectionnez
VB.NET

Imports System.Runtime.Remoting

Imports System.Runtime.Remoting.Channels

Imports System.Runtime.Remoting.Channels.Tcp

Déclarez dans la classe Form1 :

 
Sélectionnez
VB.NET

Dim remoteOperation As RemotingInterfaces.IRemoteOperation

Ajoutez dans le constructeur (New) de Form1, le code suivant :

 
Sélectionnez
VB.NET

Try

    Dim channel As TcpChannel = New TcpChannel

    ChannelServices.RegisterChannel(channel)

    remoteOperation = CType(Activator.GetObject(GetType(RemotingInterfaces.IRemoteOperation), _

        "tcp://localhost:1069/RemoteOperation"), RemotingInterfaces.IRemoteOperation)

Catch

    MessageBox.Show("Erreur de connexion au serveur")

End Try

On déclare ici un channel de type Tcp puis on instancie une référence à l'objet distant en indiquant l'interface locale, les paramètres de connexion et le nom de l'objet distant implémentant l'interface.
Nous récupérons ainsi un objet « remoteOperation » manipulable comme un objet classique, mais dont l'implémentation est sur un serveur dissocié.

IV-C. Appels aux méthodes distantes

Revenez sur la Form et double-cliquez sur le bouton « Ajouter ».
Placez dans la méthode qui est apparue (buttonAdd_Click) :

 
Sélectionnez
VB.NET

Try

    If (Not (remoteOperation) Is Nothing) Then

        Dim a As Integer = Int32.Parse(textBoxA.Text)

        Dim b As Integer = Int32.Parse(textBoxB.Text)

        textBoxResAdd.Text = remoteOperation.Addition(a, b).ToString

    End If

Catch

    MessageBox.Show("Erreur !")

End Try

Revenez sur la Form et double-cliquez sur le bouton « Incrementation ».
Placez dans la méthode qui est apparue (buttonInc_Click) :

 
Sélectionnez
VB.NET

Try

    If (Not (remoteOperation) Is Nothing) Then

        Dim valeur As Integer = Int32.Parse(textBoxValeur.Text)

        textBoxResInc.Text = remoteOperation.Incrementation(valeur).ToString

    End If

Catch

    MessageBox.Show("Erreur !")

End Try

Compilez le projet.

V. Tests

En testant notre développement, nous allons observer les comportements de l'application pour comprendre les différences entre le mode Singleton et le mode SingleCall.

Lancez le serveur (RemotingServer.exe).
Lancez le client (RemotingClient.exe).

Testez une addition simple, si le résultat apparaît, alors votre programme fonctionne correctement, bravo !

Mettez une valeur dans le champ « valeur » et cliquez sur « Incrementation ».
Au premier clic, votre résultat doit être la valeur entrée. Un clic sur « Incrémentation » correspond à un appel à la méthode de l'objet distant Incrementation().
Exemple : si vous entrez 120, alors le résultat doit être 120.
Au second clic, si vous laissez 120 en valeur, alors 240 apparaît en résultat.

Lancez un nouveau client, et indiquez 60 en valeur… le résultat est 300 (240+60).
Fermez tous les clients et lancez-en un nouveau, mettez 100 en valeur, le résultat est 400.

Ce comportement est l'illustration du fonctionnement du mode Singleton, l'objet a gardé son état entre chaque appel et indépendamment du client à l'origine de l'instanciation côté serveur initiale.

Essayez les mêmes tests en mode SingleCall (WellKnownObjectMode.SingleCall), vous observerez que pour tout nouvel appel, même pour un client unique, l'état n'est pas gardé.

Le mode SingleCall serait plus adapté pour la méthode Addition() et le mode Singleton est, par contre, intéressant pour une méthode comme Incrementation().

VI. .NET Remoting ou Web Services ?

.NET Remoting est une technologie intéressante pour les applications qui requièrent un couplage fort. C'est-à-dire pour des appels distants qui permettent de disposer de transactions, de levées d'exceptions, et autres principes applicatifs que l'on retrouve dans des développements non distribués, plus conventionnels. Avec le protocole tcp et une communication en binaire, le transport est également plus rapide.
À côté, des technologies concurrentes comme les Web Services n'apportent pas les mêmes avantages, mais proposent les intérêts d'un couplage faible basé sur des standards (SOAP, HTTP). Les Web Services permettent des échanges entre des technologies hétérogènes en mode déconnecté, ce que propose beaucoup plus difficilement .NET Remoting.
Ainsi, le choix d'une ou l'autre technologie ne peut se faire qu'en connaissant les spécificités de chacun.

Voici une comparaison Webservices/.NET Remoting ayant pour source Microsoft :

.NET Remoting

Services Web

La gestion de la durée de vie des objets repose sur un bail (avec état ou sans état).

Tous les appels de méthodes sont sans état.

IIS n'est pas nécessaire (mais l'hébergement dans IIS/ASP.NET est conseillé pour des raisons de sécurité).

IIS doit être installé sur le serveur.

Tous les types gérés sont pris en charge.

Des types de données limités sont pris en charge.

Les objets peuvent être transmis par référence et par valeur.

Les objets ne peuvent pas être transmis.

Architecture extensible non limitée aux transports HTTP ou TCP.

Le transport est limité à XML sur HTTP.

Vous pouvez connecter des récepteurs de traitement personnalisés dans le pipeline de traitement des messages.

Vous n'avez pas la possibilité de modifier les messages.

L'implémentation de SOAP est limitée. Seule l'utilisation du cryptage RPC est possible.

L'implémentation de SOAP peut utiliser le codage RPC ou le codage de documents et garantit une interopérabilité totale avec d'autres plates-formes de services Web.

Étroitement intégré.

Librement intégrés.

Remarques sur le tableau :

- .NET Remoting et les Web services fonctionnent aussi avec Mono, le portage libre du framework .NET.

- La sécurité de .NET Remoting est un de ses points faibles, il est dommage de devoir passer par un serveur web et donc HTTP (IIS dans le tableau) pour sécuriser une application distribuée.

- Pour la sécurité des Webservices, vous pouvez consulter les articles suivants :
https://leduke.developpez.com/WebService/
https://defaut.developpez.com/tutoriel/dotnet/webservices/https/

- La possibilité d'effectuer des pré et posttraitements sur les messages n'a pas été évoquée dans cet article. Il s'agit d'une fonctionnalité avancée de .NET Remoting.
Plus d'informations ici : MSDN.

- On peut réaliser un Web Service qui semble garder un état en utilisant les Sessions. Mais c'est plus lourd à gérer qu'en .NET Remoting.

VII. Téléchargements

Téléchargez les sources VB.NET de cet article.
Téléchargez la version Delphi.NET (par Laurent Dardenne).

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

Copyright © 2013 Minosis Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.