Cours de C# pour l'ESSI - ESSI2 Reseau - TP1 RE - revisited (.NET Remoting)

RACINE
Voir dans une fenêtre à part Cliquez ici pour voir la page dans un explorateur séparé.



Partie 1 : Introduction

Je rappellerai à mon aimable lecteur(trice) que ce cours est sponsorisé par Microsoft France. Par conséquent ce sont bien évidement des technologies développées ou utilisées par Microsoft (mais qui ne sont pas forcément sa propriété) que je présenterai ici.

Le but est ici de présenter le pendant du TP1 du cours de Réseaux (copie locale) de Mme AM DERY-PINNA en 2ème année de l'ESSI où nous avons (ESSIens) appris à utiliser RMI (Remoting Method Invoking) avec Java. C'est notamment par ce moyen là que Java "fait" du Client-Serveur, objets répartis, etc ...
Il existe peut-être (libre aux curieux de chercher) des portages de RMI vers d'autres langages, voir même vers C# et le monde .NET. Ceci ne sera pas présenté ici. Je vais m'efforcer de présenter de manière SIMPLE mais SUFFISAMENT DETAILLEE comment faire du Client-Serveur avec C#. Nous allons utiliser .NET Remoting pour ça.

Ce deuxième TP est relativement court, et vous pourrez le faire en 1h ou 2, si vous avez compris ce que vous avez fait en Java. Je propose deux versions des sources : une version "simple" complètement fonctionnelle et une version "complexe" qui utilise de la réflexion.

Pour utiliser .NET Remoting, vous devez avoir installé sur votre poste AU MOINS :
  1. Windows XP Pro ou 2000 avec SP2 ou NT4 avec SP6a
  2. Internet Explorer 5.01
  3. IIS (mais pas dans tout les cas)
  4. .NET Framework SDK
  5. un éditeur de votre choix (emacs ou VS.NET suivant les courants de pensée)

Il est plus que conseillé de se référer à la présentation C# vs. Java (SURTOUT si vous n'avez jamais fait de C#) ainsi qu'aux autres cours en cas difficulté. Notamment le cours sur les WebServices et RMI vs. WebServices !!!
Si vous constatez des erreurs, des imprécisions ou que vous avez des problèmes avec ce TP, adressez vous à l'auteur.

Tout le matériel qui est présenté n'est nullement un cours officiel de l'ESSI ou de Microsoft. Il a été produit par l'auteur et en est l'exclusive propriété.
Toutes remarques pouvant aider à l'améliorer ou à corriger les diverses erreurs pouvant subsister sont les bienvenues. (email auteur)

retour à l'index

Partie 2 : Concepts

En Java, c'est par RMI que passe les appels de méthodes distant. Un serveur RMI (rmiregistry) tourne sur votre machine, où il joue le rôle "d'annuaire de service". Vous devez connaître le nom du service auquel vous désirez accéder, et évidement son interface. Quand votre requête aboutit, vous passez par une classe souche (ou stubs) pour invoquer les méthodes de l'objet distant. La sérialisation est en binaire, ou plutôt en "natif Java".

Avec les WebServices, vous possédiez aussi une classe souche (à générer à partir du contrat WSDL du WebService) mais votre connexion n'existait que le temps de l'exécution de votre methode. De plus, vous passiez par IIS (par defaut dumoins).

.NET Remoting


Avec .NET Remoting, le serveur publie un service. C'est une instance d'une certaine classe implémentant une certaine interface. Cette instance peut être en mode SingleCall ou Singleton : dans le premier cas, une instance sera crée pour chaque client, dans l'autre, tout les clients partagerons la même. Vous pouvez passer par HTTP ou TCP (à votre convenance, voir par d'autres protocoles) et votre objet peut être utilisé par référence (et pas à travers un décorateur proxy). La durée de vie d'un objet distant est définie par contrat, et est gérée entièrement par le framework

L'objet distribué est accessible par une URI (Uniform Resource Identifier) de la forme "tcp://monserveur.com:12345/monobjet" si vous utilisez TCP, sur la machine de DNS monserveur.com sur le port 12345 sous le nom "monobjet".

Une grosse différence avec RMI ou les WebServices, vous ne créez pas explicitement de classe proxy. Ceci est géré de manière transparente pour vous par le framework. Ici, avec TCP, pas de serialisation SOAP mais du binaire pas très portable hors .NET (si vous voulez du portable, il y a les WebServices ). Par contre, la sérialisation sera en SOAP si vous utilisez un channel HTTP.

Dans l'exemple, nous allons publier une classe MySurnomService qui implémente l'interface ISurnomService. Cette classe permet d'enregistrer des surnoms pour des étudiants, d'en oter et de les lister. Peu importe le code, il n'est là que pour donner une raison d'être au programme.

retour à l'index

Partie 3 : Pratique

Cliquez pour télécharger Cliquez ici pour obtenir le .NET Framework SDK (130 Mo).
Cliquez pour télécharger Cliquez ici pour obtenir le source du client et du serveur de surnoms.

Le Service

Peu de chose à savoir. Il n'est pas necessaire qu'il implémente une interface pour fonctionner, mais sans cela, vous distribuez votre classe à vos clients et avoir un objet distant devient ... inutile. Donc va pour l'interface.

Seul chose OBLIGATOIRE, votre service doit dériver de MarshalByRefObject définie dans le namespaceSystem. Ceci permet l'objet d'être passé par le réseau et à travers les différents domaines d'application, et ceci par référence. C'est d'ailleur en héritant de cette classe que vous pourrez redéfinir des contrat de durée de vie de votre objet. Pour ceci, voyez la méthode InitializeLifetimeService().

retour à l'index

Le Serveur

Le canal

Dans .NET pour communiquer il faut ouvrir un canal. Nous avons le choix (de base) entre TCP ou HTTP. Nous prendrons TCP pour profiter au maximum d'avoir une sérialisation binaire. Il faut inclure 3 namespaces pour faire du remoting par TCP :
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
Ensuite, on créé un TcpChannel sur le port souhaité et on l'enregistre auprès de la classe ChannelServices qui a pour charge de gérer l'enregistrement des cannaux.
TcpChannel chan = new TcpChannel (12345);    

ChannelServices.RegisterChannel (chan);

La publication

On publie ensuite un Type. La notion de Type va au-delà de la notion de classe, et représente une classe ou un type valeur (int, double,...) ou un pointeur et autres. C'est avec cette classe abstraite que .NET gère les classes pour la réflexion.

Il faut aussi fournir l'URI sous laquelle on va publier les "instances" de ce Type, et si ce sera dans le mode SingleCall (comme pour les WebServices) ou Singleton (une seule instance sera partagée par les clients). Notez que c'est le Type de notre implémentation que l'on publie et pas l'interface.

L'enregistrement se fait auprès de la classe RemotingConfiguration qui contient des méthodes concernant le remoting sous .NET.
1: RemotingConfiguration.RegisterWellKnownServiceType(
2:           Type.GetType("SurnomRemote.MySurnomService"), ///le Type
3:           "SurnomService",                              ///l'URI
4:           WellKnownObjectMode.Singleton);               ///mode
Voilà, votre serveur est prêt et attent les connexions.

retour à l'index

Le Client

Le canal

On fonctionne ici de manière symétrique du serveur, donc il nous faut un canal pour communiquer. Il est toutefois de bon alloi de ne pas préciser quel numéro de port on veut, mais de laisser le système nous en attribuer un. Le code est IDENTIQUE à son pendant côté serveur. Le voici :
TcpChannel chan = new TcpChannel ();    

ChannelServices.RegisterChannel (chan);

Référence sur l'objet distant

On veut récuperer une référence sur un objet distant dont on ne connais pas le type mais dont on connais une interface qu'il implémente. Cette interface est ISurnomSrv dans notre cas.

Pour faire cela, il faut l'URI du service, ainsi que le Type de l'interface implémentée par le service (et qui nous interresse). C'est la classe Activator qui permet de récupérer une référence sur un objet distant.
ISurnomService obj = (ISurnomService)Activator.GetObject(
                         Type.GetType ("SurnomRemote.ISurnomService"),
                         "tcp://localhost:12345/SurnomService");
Vous pouvez maintenant utiliser votre objet comme si c'était un objet local.
Console.WriteLine("Ajout : Takeshi Kitano=beat");
obj.ajouterSurnom ("Takeshi Kitano", "beat");

Console.WriteLine("Liste");
foreach (String s in obj.listerSurnoms ("Takeshi Kitano"))
  Console.Write("\t" + s);

retour à l'index

Documentation .NET Framework SDK


retour à l'index

Partie 4 : Le mot de la fin

Conclusion

Ceci est UNE manière de faire du remoting sous .NET, et ce n'est pas la seule. Elle représente la méthode standard de faire du remoting, mais certaines apportent plus de chose (enregistrement de type et initialisation par des new au lieu des barbares Activator.GetObject(..)).

retour à l'index

Remerciements

Mesdames Anne-Marie DERY-PINNA et Mireille BLAY-FORNARINO, professeurs à l'ESSI, pour leurs encouragements.
Monsieur Laurent ELLERBACH, responsable relation études supérieures chez Microsoft France, pour son soutien et ses idées.

retour à l'index

Sources

Sur le Web : Bibliographie :

retour à l'index





par Alain Vizzini (vizzini@essi.fr)
pour l'ESSI & Microsoft, création 26-10-2002, dernière màj 02-02-2003


pages vues depuis le 14 oct. 2002