< Programmation C sharp

Une application .NET peut être un service distant et peut s'exécuter comme :

Serveur RPC

Serveur Remoting

À l'aide de la librairie System.Runtime.Remoting à placer dans l'application servante et cliente, celles-ci peuvent partager une classe par Marshaling suivant un canal Http, Ipc ou Tcp.

Le remoting utilise les échanges RPC.

Dans cette solution :

  1. INTERFACE : IRemoteMath est une librairie de classe
  2. SERVER : RemoteServer est une application console
  3. CLIENT : RemoteClient est une application console

L'interface partagée

Une interface IOperations comprenant un prototype d'addition.

namespace IRemoteMath
{
    public interface IOperations
    {
        int Addition(int a, int b);
    }
}

Le serveur

Le serveur est l'application qui distribue ses services. Pour qu'elle déserve à distance, il lui faut :

  • Dans ses références :
  1. System.Runtime.Remoting
  2. Le namespace d'IRemoteMath
  • Implémenter IOperations

Implémenter IOperations

La classe à servir doit faire partie du service distributeur ici RemoteServer

namespace RemoteServer
{
    public class RemoteOperations : MarshalByRefObject, IRemoteMath.IOperations
    {
        // l'objet aura une durée de vie illimitée
        public override object InitializeLifetimeService()
        {
            return null;
        }
		
        // cette méthode sera servie
        public int Addition(int a, int b)
        {
            Console.WriteLine(String.Format("> Addition() : a={0}, b={1}", a, b));
            return a + b;
        }
    }
}

MarshalByRefObject signifie que RemoteOperations fera l'objet d'un marshaling.

Configurer RemoteMain

Pour écouter les appels, le serveur doit créer un canal d'écoute sur un port et enregistrer le service à distribuer.

using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;

namespace RemoteServer
{
    class RemoteMain
    {
        [STAThread]
        static void Main(string[] args)
        {
            try
            {
                // Création du canal sur le port 1050
                TcpChannel channel = new TcpChannel(1050);
                // Enregistrement du canal
                ChannelServices.RegisterChannel(channel);
                // Distribution de l'objet en mode singleton
                RemotingConfiguration.RegisterWellKnownServiceType(
                    typeof(RemoteOperations),
                    "RemoteOperations",
                    WellKnownObjectMode.Singleton);

                Console.WriteLine("Serveur démarré");
                Console.ReadLine();
            }
            catch
            {
                Console.WriteLine("Erreur au démarrage");
                Console.ReadLine();
            }
        }
    }
}
  1. [STAThread] au point d'entrée instruit le main comme "appartement" pour cloisonner les traitements au partage de ses ressources.
  2. RemotingConfiguration.RegisterWellKnownServiceType enregistre RemoteOperations dans ses services
  3. Le canal est ici en TCP

Le client

Le client appelle les services. Pour qu'elle soit servie, il lui faut :

  • Dans ses références :
  1. System.Runtime.Remoting
  2. Le namespace d'IRemoteMath
using System;
using System.Text;

// Remoting
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;

namespace RemoteClient
{
    class RemoteTestClient
    {
	// préparation de l'objet distribué
	private IRemoteMath.IOperations remoteOperation;
		
	public RemoteTestClient()
	{
            try
            {	
		// init channel - facultatif
                // TcpChannel channel = new TcpChannel();
                // ChannelServices.RegisterChannel(channel);
		// init IOperations < RemoteServer.RemoteOperations
                this.remoteOperation = (IRemoteMath.IOperations)Activator.GetObject(
                    typeof(IRemoteMath.IOperations),
                    "tcp://localhost:1050/RemoteOperations");
            }
            catch { 
                Console.WriteLine("Erreur de connexion"); 
            }
	}
		
	public void RemoteAddition(int a, int b)
	{
	    try
            {
                if (this.remoteOperation != null)
                {
                    Console.WriteLine("Résultat : " + this.remoteOperation.Addition(a, b).ToString());
                }
            }
            catch 
	    {
		Console.WriteLine("Erreur à l'appel");
	    }
	}
		
	[STAThread]
        static void Main()
        {
            RemoteTestClient Client = new RemoteTestClient();
	    Client.RemoteAddition(15, 20);
			
	    System.Threading.Thread.Sleep(5000);
        }
    }
}
  1. [STAThread] indique qu'on est dans le même type de cloisonnement des threads que pour server.
  2. remoteOperation dépile la classe reçu par TCP permettant l'utilisation de ses propriétés.

Application

  1. Pour effectuer le test, il faut compiler les trois projets IRemoteMath,RemoteServer,RemoteClient
  2. Executer RemoteServer.exe avant RemoteClient.exe

Le résultat du client devrait être :

Résultat : 35

Le message du serveur devrait être :

> Addition() : a=15, b=20 

Serveur de pipes

Serveur de queue

Cet article est issu de Wikibooks. Le texte est sous licence Creative Commons - Attribution - Partage dans les Mêmes. Des conditions supplémentaires peuvent s'appliquer aux fichiers multimédias.