Remoting

.::Home::.

.::Introduzione::.

1.Panoramica

4.DataBase

.::Presentazioni PPT::.

.::Link::.

.::DownLoad::.

 

Introduzione

.NET remoting fornisce una struttura che consente agli oggetti di interagire fra loro su domini di applicazione. La struttura fornisce una serie di servizi, tra cui supporto di attivazione e durata, oltre a canali di comunicazione che si occupano del trasporto di messaggi verso e da applicazioni remote. I formattatori vengono utilizzati per la codifica e decodifica dei messaggi, prima che il canale li trasmetta. Le applicazioni possono utilizzare la codifica binaria in caso di prestazioni critiche, oppure la codifica XML laddove è essenziale l'interoperabilità con altre strutture remote. Tutte le codifiche XML utilizzano il protocollo SOAP per la trasmissione dei messaggi da un application domain a un altro. Il remoting è stato progettato pensando alla protezione; sono disponibili una serie di hook che fanno in modo che i sink di protezione abbiano accesso ai messaggi, insieme al flusso serializzato, prima che il flusso venga trasmesso nel canale.

La gestione della durata degli oggetti remoti senza un supporto della struttura sottostante non è sempre facile. .NET remoting mette a disposizione una serie di modelli di durata tra cui scegliere, suddivisi in due categorie:

  • Oggetti attivati da client

  • Oggetti attivati da server

Gli oggetti attivati da client sono controllati da un programma di gestione durata basato su lease, che assicura che l'oggetto venga sottoposto a garbage collection alla scadenza del lease. Nel caso di oggetti attivati da server, gli sviluppatori possono selezionare un modello "single call" o "singleton".

Oggetti remoti

Uno degli obiettivi principali di una struttura di remoting è fornire l'infrastruttura in grado di nascondere le complessità dei metodi di chiamata per oggetti remoti e riportarne i risultati. Qualsiasi oggetto esterno all' application domain del mittente dovrebbe essere considerato remoto, anche se gli oggetti vengono eseguiti sullo stesso computer. All'interno dell' application domain, tutti gli oggetti vengono passati in base al riferimento mentre i tipi di dati primitivi in base al valore. Poiché i riferimenti a oggetti locali sono validi solo all'interno dell'application domain in cui vengono creati, non è possibile spostarli o riportarli dalle chiamate remote di metodi in questa forma. Tutti gli oggetti locali che devono attraversare il confine dell' application domain devono passare in base al valore e dovrebbero essere contrassegnati dall'attributo personalizzabile [serializable], oppure devono implementare l'interfaccia ISerializable. Quando l'oggetto viene passato in forma di parametro, la struttura serializza l'oggetto e lo trasporta all'application domain di destinazione, dove l'oggetto verrà ricomposto. Gli oggetti locali che non è possibile serializzare non possono essere spostati in un altro application domain quindi vengono considerati non remoti.

È possibile modificare qualsiasi oggetto in un oggetto remoto facendolo derivare da MarshalByRefObject. Quando un client attiva un oggetto remoto, riceve un proxy per questo oggetto. Tutte le operazioni su questo proxy vengono indirizzate in modo da consentire all'infrastruttura remota di intercettare e inoltrare correttamente le chiamate. Questa operazione di indirizzamento influisce sulle prestazioni, ma il compilatore JIT ed EE (execution engine) sono stati ottimizzati per evitare inutili penalizzazioni delle prestazioni, quando gli oggetti proxy e remoti si trovano nello stesso application domain. Nei casi in cui invece questi oggetti si trovano in domini di applicazione diversi, tutti i parametri di chiamata del metodo nello stack vengono convertiti in messaggi e spostati nel application domain remoto, dove i messaggi vengono messi nuovamente in un frame dello stack e il metodo viene richiamato. La stessa procedura viene utilizzata per riportare i risultati della chiamata del metodo.

Oggetti proxy

Gli oggetti proxy vengono creati quando un client attiva un oggetto remoto. L'oggetto proxy agisce da rappresentante degli oggetti remoti e controlla che tutte le chiamate fatte sul proxy vengano inoltrate all'istanza corretta dell'oggetto remoto. Per capire esattamente come funzionano gli oggetti proxy è necessario esaminarli più da vicino. Quando un client attiva un oggetto remoto, la struttura crea un'istanza locale della classe TransparentProxy che contiene un elenco di tutte le classi, insieme a metodi di interfaccia dell'oggetto remoto. Dal momento che la classe TransparentProxy una volta creata viene registrata con CLR, tutte le chiamate del metodo sul proxy vengono intercettate dal runtime. La chiamata viene quindi esaminata per stabilire se si tratta di un metodo valido dell'oggetto remoto e se un'istanza di questo oggetto si trova nello stesso application domain del proxy. Se tutto ciò è vero, una chiamata semplice del metodo viene indirizzata all'oggetto reale. Se l'oggetto si trova in un application domain diverso, i parametri di chiamata sullo stack vengono assemblati in un oggetto IMessage e inoltrati a una classe RealProxy richiamando il relativo metodo Invoke. Questa classe (o meglio, un'implementazione interna della classe) si occupa di inoltrare i messaggi all'oggetto remoto. Entrambe le classi TransparentProxy e RealProxy vengono create automaticamente quando viene attivato un oggetto remoto, ma viene restituito al client solo TransparentProxy.

Per una migliore comprensione di questi oggetti proxy, dobbiamo parlare brevemente di ObjRef. Nella Sezione Attivazione è contenuta una descrizione dettagliata di ObjRef. Lo scenario seguente descrive in breve il modo in cui ObjRef e le due classi proxy sono correlate. Si tratta di una descrizione molto ampia del processo ed esistono alcune variazioni, a seconda che gli oggetti siano attivati da client o da server e se si tratta di oggetti singleton o single-call.

  • Un oggetto remoto viene registrato in un application domain su un computer remoto. Viene eseguito il marshalling dell'oggetto per creare un ObjRef. Questo ObjRef contiene tutte le informazioni necessarie per individuare e accedere all'oggetto remoto da qualsiasi punto della rete. Queste informazioni comprendono il nome della classe, la relativa gerarchia (gli elementi padre), i nomi di tutte le interfacce implementate dalla classe, l'oggetto URI (Uniform Resource Identifier) e i particolari di tutti i canali disponibili che sono stati registrati. La struttura di remoting utilizza l'oggetto URI per richiamare l'istanza ObjRef creata per l'oggetto remoto nel momento in cui riceve una richiesta relativa a questo oggetto.

  • Un client attiva un oggetto remoto richiamando new o una delle funzioni di Activator come CreateInstance. Nel caso di oggetti attivati da server, viene creato un TransparentProxy per l'oggetto remoto nel application domain del client, quindi viene restituito al client senza effettuare alcuna chiamata remota. L'oggetto remoto viene attivato solo quando il client richiama un metodo sull'oggetto remoto. Questo scenario ovviamente non è adatto per gli oggetti attivati da client, in quanto il client prevede che la struttura attivi l'oggetto secondo la richiesta. Quando un client richiama uno dei metodi di attivazione, viene creato un proxy di attivazione sul client e viene avviata una chiamata remota per un attivatore remoto sul server, utilizzando l'URL e l'oggetto URI come endpoint. L'attivatore remoto attiva l'oggetto e un oggetto ObjRef viene trasmesso al client, dove viene eseguito l'unmarshalling per creare un TransparentProxy che viene infine restituito al client.

  • Durante l'unmarshalling, ObjRef viene analizzato per ottenere le informazioni sul metodo dell'oggetto remoto e vengono creati gli oggetti TransparentProxy e RealProxy. Il contenuto di ObjRef analizzato viene inserito nelle tabelle interne di TransparentProxy prima che quest'ultimo venga registrato con il CLR.

TransparentProxy è una classe interna che non può essere sostituita nè estesa. Allo stesso tempo, le classi RealProxy e ObjRef sono pubbliche e possono essere estese e personalizzate laddove necessario. La classe RealProxy è un elemento ideale per eseguire ad esempio il bilanciamento del carico, perché gestisce tutte le chiamate di funzioni su un oggetto remoto. Quando viene richiamato Invoke, una classe che deriva da RealProxy può ottenere informazioni di carico sui server della rete e indirizzare la chiamata a un server adatto. È necessario un MessageSink per ObjectURI richiesto dal canale e richiamare SyncProcessMessage o AsyncProcessMessage per inoltrare la chiamata all'oggetto remoto richiesto. Quando la chiamata viene reinviata, il parametro di ritorno viene riportato allo stack, richiamando PropagateMessageToProxy sulla classe RemotingServices.

Di seguito è riportato un frammento di codice che mostra come utilizzare una classe derivata RealProxy.

   MyRealProxy proxy = new MyRealProxy(typeof(Foo));
Foo obj = (Foo)proxy.GetTransparentProxy();
int result = obj.CallSomeMethod();

È possibile inoltrare il valore TransparentProxy ottenuto sopra verso un altro application domain. Quando il secondo client cerca di richiamare un metodo sul proxy, la struttura di remoting prova a creare un'istanza di MyRealProxy e se all'assembly è disponibile, tutte le chiamate verranno indirizzate attraverso questa istanza. Se l'assembly non è disponibile, le chiamate vengono indirizzate attraverso il RealProxy di remoting predefinito.

È possibile personalizzare in modo semplice ObjRef fornendo dei valori sostitutivi per le proprietà ObjRef, TypeInfo, EnvoyInfo e ChannelInfo. Il codice seguente indica come eseguire questa operazione.

public class ObjRef {
  public virtual IRemotingTypeInfo TypeInfo 
  {
    get { return typeInfo;}
    set { typeInfo = value;}
  }

  public virtual IEnvoyInfo EnvoyInfo
  {
    get { return envoyInfo;}
    set { envoyInfo = value;}
  }

  public virtual IChannelInfo ChannelInfo 
  {
    get { return channelInfo;}
    set { channelInfo = value;}
  }
}

Canali

I canali vengono utilizzati per trasmettere messaggi verso e da oggetti remoti. Quando un client richiama un metodo su un oggetto remoto, i parametri e altri dettagli relativi alla chiamata vengono trasmessi all'oggetto remoto attraverso il canale. I risultati della chiamata tornano poi al client seguendo la stessa procedura. Un client è in grado di selezionare qualsiasi canale registrato sul "server" per comunicare con l'oggetto remoto. In questo modo gli sviluppatori possono selezionare i canali più adatti alle proprie esigenze. È possibile inoltre personalizzare tutti i canali esistenti o creare nuovi canali che utilizzino protocolli di comunicazione diversi. La scelta dei canali avviene secondo le regole descritte di seguito:

  • È necessario registrare almeno un canale con la struttura di remoting prima di poter richiamare un oggetto remoto. I canali devono essere registrati prima degli oggetti.

  • I canali vengono registrati per application domain. È possibile avere diversi domini di applicazione in un solo processo. Quando un processo termina, tutti i canali registrati vengono automaticamente distrutti.

  • Non è consentito registrare lo stesso canale in ascolto su una stessa porta più di una volta. Anche se i canali vengono registrati per application domain, più domini di applicazione sullo stesso computer non possono registrare lo stesso canale in ascolto sulla stessa porta.

  • I client possono comunicare con un oggetto remoto utilizzando qualsiasi canale registrato. La struttura di remoting assicura che l'oggetto remoto sia collegato al canale adatto quando un client tenta di stabilire una connessione ad esso. Il client si occupa di richiamare RegisterChannel sulla classe ChannelService prima di provare a comunicare con un oggetto remoto.

Tutti i canali derivano da IChannel e implementano IChannelReceiver o IchannelSender, a seconda dello scopo del canale. La maggior parte di essi implementa le interfacce di ricevente e mittente per consentire loro di comunicare in entrambe le direzioni. Quando un client richiama un metodo su un proxy, la chiamata viene intercettata dalla struttura di remoting e trasformata in un messaggio, che viene inoltrato alla classe RealProxy (o meglio, a un'istanza di una classe che implementa RealProxy). RealProxy inoltra il messaggio al sink per l'elaborazione. Un sink di messaggio si occupa di stabilire la connessione con il canale registrato dall'oggetto remoto e di trasportare il messaggio attraverso il canale (in un altro application domain), da cui viene indirizzato all'oggetto remoto stesso. Quando un oggetto remoto viene attivato, un sink di messaggio in grado di comunicare con l'oggetto remoto viene recuperato dal canale prescelto dal client, richiamando CreateMessageSink su questo canale.

Un aspetto poco chiaro della struttura di remoting è il rapporto tra oggetti remoti e canali. Ad esempio, in che modo un oggetto remoto SingleCall attende che i client si connettano, se l'oggetto viene attivato solo quando arriva la chiamata?

Una parte di questa operazione dipende dal fatto che gli oggetti remoti condividono i canali. Un oggetto remoto non possiede un canale. Le applicazioni server che contengono gli oggetti remoti devono registrare i canali necessari e gli oggetti da esporre con la struttura di remoting. Quando un canale viene registrato, automaticamente comincia ad attendere le richieste del client alla porta specificata. Quando un oggetto remoto viene registrato, viene creato un ObjRef per l'oggetto, che viene memorizzato in una tabella. Quando arriva una richiesta su un canale, la struttura di remoting esamina il messaggio per determinare l'oggetto di destinazione e controlla la tabella dei riferimenti all'oggetto per individuare il riferimento all'interno della tabella. Se questo riferimento viene individuato, l'oggetto di destinazione della struttura viene recuperato dalla tabella o attivato quando è necessario, e la struttura inoltra la chiamata all'oggetto. Nel caso di chiamate sincrone, la connessione del client resta attiva per la durata della chiamata del messaggio. Dal momento che ogni connessione client viene gestita nel relativo thread, un singolo canale può essere utilizzato da più client contemporaneamente.

La protezione è un fattore importante nella creazione di applicazioni aziendali e gli sviluppatori devono essere in grado di aggiungere funzionalità di protezione, per esempio autorizzazione o codifica per le chiamate remote di metodo, per soddisfare i requisiti aziendali. Per far fronte a questa esigenza, è possibile personalizzare i canali per fornire agli sviluppatori il controllo del meccanismo concreto di trasmissione dei messaggi da e verso l'oggetto remoto. Tutti i messaggi passano attraverso SecuritySink, TransportSink e FormatterSink prima di essere trasferiti all'applicazione remota, da cui poi passano attraverso gli stessi sink in ordine inverso.

Canale HTTP

Il canale HTTP trasporta i messaggi da e verso oggetti remoti utilizzando il protocollo SOAP. Tutti i messaggi passano attraverso il formattatore SOAP, dove il messaggio viene trasformato in XML e serializzato, e le intestazioni SOAP vengono aggiunte al flusso. È possibile inoltre specificare il formattatore binario, che crea un flusso di dati binari. Questo flusso viene quindi trasportato all'URI di destinazione tramite il protocollo HTTP.

Canale TCP

Il canale TCP utilizza un formattatore binario per serializzare i messaggi in un flusso binario e trasportare il flusso all'URI di destinazione tramite il protocollo TCP.

Attivazione

La struttura di remoting supporta l'attivazione da server e client di oggetti remoti. L'attivazione da server si utilizza in genere quando gli oggetti remoti non sono necessari per la conservazione di uno stato tra le chiamate del metodo; si utilizza anche nei casi in cui più client richiamano metodi sulla stessa istanza di oggetto e l'oggetto conserva lo stato tra le chiamate delle funzioni. Allo stesso tempo, gli oggetti attivati da client vengono istanziati dal client, che gestisce la durata dell'oggetto remoto utilizzando un sistema basato su lease fornito a tale scopo.

È necessario registrare tutti gli oggetti remoti con la struttura remota prima che i client possano accedervi. La registrazione degli oggetti viene eseguita in genere da un'applicazione host che avvia, registra uno o più canali con ChannelServices, registra uno o più oggetti remoti con RemotingServices e aspetta che l'operazione sia terminata. I canali registrati e gli oggetti sono disponibili solo mentre il processo che li ha registrati è aperto. Quando il processo termina, tutti i canali e gli oggetti registrati vengono automaticamente rimossi dai servizi di remoting in cui si trovano. Le informazioni riportate di seguito sono necessarie per la registrazione di un oggetto remoto con la struttura:

  1. Il nome del tipo di oggetto remoto.

  2. L'oggetto URI che i client utilizzeranno per individuare l'oggetto.

  3. La modalità oggetto richiesta per l'attivazione da server, che può essere SingleCall o Singleton.

Un oggetto SingleCall crea un'istanza di classe per ogni chiamata del client, anche se le chiamate provengono dallo stesso client. L'invocazione successiva, sarà sempre servita da una differente istanza del server anche se la precedente non è stata ancora riciclata dal sistema.

Un oggetto Singleton invece non presenta mai più di una istanza contemporaneamente. Se una istanza è già esistente la richiesta viene soddisfatta da quella istanza. Se l'istanza non esiste, alla prima richiesta viene creata dal server e tutte le successive richieste vengono soddisfatte da quella istanza.

È possibile registrare un oggetto remoto richiamando RegisterWellKnownType, passando le informazioni riportate sopra come parametri, oppure memorizzarle in un file di configurazione, richiamare ConfigureRemoting e passare il nome del file di configurazione come parametro. Queste due funzioni possono essere entrambe utilizzate per registrare oggetti remoti perché svolgono esattamente la stessa operazione. La seconda è più adatta perché il contenuto del file di configurazione può essere alterato senza dover compilare di nuovo l'applicazione host. Il frammento di codice seguente mostra come registrare la classe HelloService come oggetto remoto SingleCall.

RemotingServices.RegisterWellKnownType(
  "server",
  "Samples.HelloServer",
  "SayHello",
   WellKnownObjectMode.SingleCall);

In questo caso "server" è il nome del assembly, HelloServer è il nome della classe e SayHello è l'oggetto URI

Quando l'oggetto viene registrato, la struttura crea un riferimento per questo oggetto remoto ed estrae i metadati necessari per l'oggetto dall'assembly. Queste informazioni, insieme all'URI e al nome dell'assembly, vengono poi memorizzate nel riferimento dell'oggetto all'interno di una tabella della struttura di remoting, utilizzata per la registrazione degli oggetti remoti registrati. Si noti che l'oggetto remoto stesso non viene istanziato dal processo di registrazione, ma solo quando un client tenta di richiamare un metodo sull'oggetto oppure attiva l'oggetto dal lato client.

A questo punto, qualsiasi client che conosca l'URI di questo oggetto può ottenere un proxy registrando il canale preferito con ChannelServices e attivare l'oggetto richiamando new, GetObject o CreateInstance. Il frammento di codice seguente costituisce un esempio di questa operazione:

     ChannelServices.RegisterChannel(new TCPChannel);
      HelloServer obj = (HelloServer)Activator.GetObject(
         typeof(Samples.HelloServer), "tcp://localhost:8085/SayHello");

In questo caso "tcp://localhost:8085/SayHello" specifica che l'utente intende stabilire una connessione all'oggetto remoto nell'endpoint SayHello utilizzando TCP sulla porta 8085. Il compilatore richiederà le informazioni sul tipo relative alla classe HelloServer quando questo codice client viene compilato. Queste informazioni vengono fornite in uno dei seguenti modi:

  • Fornire un riferimento all'assembly in cui la classe HelloService viene memorizzata.

  • Dividere l'oggetto remoto in un'implementazione e una classe di interfaccia e utilizzare l'interfaccia come riferimento per la compilazione del client.

  • Utilizzare lo strumento SOAPSUDS per estrarre i metadati richiesti direttamente dall'endpoint. Questo strumento collega all'endpoint fornito, estrae i metadati e crea un assembly o un codice sorgente che può essere poi utilizzato per compilare il client.

È possibile utilizzare GetObject o new per l'attivazione del server. L'oggetto non viene istanziato quando viene effettuata una di queste chiamate. In pratica non viene generata alcuna chiamata di rete. La struttura ottiene le informazioni sufficienti dai metadati per creare il proxy senza connettersi affatto all'oggetto remoto. Viene solo stabilita una connessione di rete quando il client richiama un metodo sul proxy. Quando la chiamata arriva al server, la struttura estrae l'URI dal messaggio, esamina le tabelle della struttura di remoting per individuare il riferimento per l'oggetto corrispondente all'URI, quindi istanzia l'oggetto se necessario, inoltrando la chiamata del metodo all'oggetto. Se l'oggetto è registrato come SingleCall, viene eliminato al termine della chiamata del metodo. Per ciascun metodo invocato viene creata una nuova istanza dell'oggetto. L'unica differenza tra GetObject e new è che il primo consente di specificare un URL come parametro, mentre il secondo lo ottiene dalla configurazione.

È possibile utilizzare CreateInstance o new per gli oggetti attivati da client. Entrambi consentono di istanziare un oggetto utilizzando i costruttori con dei parametri. La durata degli oggetti attivati da client è controllata dal servizio di leasing, fornito dalla struttura di remoting. Il leasing di oggetti è descritto nella sezione successiva.

Durata oggetti con leasing

Ogni application domain contiene un programma di gestione lease all'interno del dominio. Tutti i lease vengono esaminati periodicamente per controllare le scadenze. Se un lease è scaduto, è possibile richiamare gli sponsor del lease dando loro l'opportunità di rinnovarlo. Se nessuno degli sponsor decide per il rinnovo, il programma di gestione rimuove il lease e l'oggetto viene sottoposto a garbage collection. Questo programma gestisce un elenco che ordina tutti i lease in base al tempo residuo del contratto. I lease più vicini alla scadenza vengono collocati ai primi posti dell'elenco.

I lease implementano l'interfaccia ILease e contengono una serie di proprietà, che determinano i criteri e i metodi da rinnovare. I lease possono essere rinnovati su richiesta. Ogni volta che viene richiamato un metodo sull'oggetto remoto, il tempo di lease viene impostato sul massimo valore corrente di LeaseTime più RenewOnCallTime. Alla scadenza del LeaseTime, viene richiesto allo sponsor di rinnovare il lease. A causa delle reti talvolta poco affidabili, potrebbe accadere che lo sponsor del lease non sia disponibile, quindi per essere sicuri di non lasciare oggetti bloccatisul server, ogni lease ha un SponsorshipTimeout. Questo valore specifica il tempo di attesa per la risposta dello sponsor prima che il lease venga chiuso. Se SponsershipTimeout è nullo, il valore CurrentLeaseTime verrà utilizzato per stabilire la scadenza del lease. Se CurrentLeaseTime ha un valore zero, il lease non scade. È possibile utilizzare la configurazione o le API per sostituire i valori predefiniti di InitialLeaseTime, SponsorshipTimeout e RenewOnCallTime.

Il programma di gestione lease crea un elenco degli sponsor (che implementano l'interfaccia ISponsor) con ordine decrescente di sponsorship. Quando occorre uno sponsor per rinnovare i termini del lease, viene interpellato uno o più sponsor dalle prime voci dell'elenco. I primi nomi sono quelli degli sponsor che hanno richiesto in precedenza i tempi di rinnovo di lease più lunghi. Se uno sponsor non risponde nell'intervallo di tempo SponsorshipTimeOut, il suo nome viene eliminato dall'elenco. È possibile ottenere un lease richiamando GetLifetimeService, passando il lease richiesto come parametro. Questa chiamata costituisce un metodo statico della classe RemotingServices. Se l'oggetto è locale al dominio dell'applicazione, il parametro per questa chiamata è un riferimento locale all'oggetto, e il lease restituito è un riferimento locale al lease. Se l'oggetto è remoto, il proxy viene passato come parametro e al mittente viene restituito un proxy trasparente per il lease.

Gli oggetti possono fornire i relativi lease e avere così il controllo della durata; ciò è possibile sostituendo il metodo InitializeLifetimeService a MarshalByRefObject come indicato di seguito:

public class Foo : MarshalByRefObject {
public override Object InitializeLifetimeService()
{
ILease lease = (ILease)base.InitializeLifetimeService();
if (lease.CurrentState == LeaseState.Initial) {
lease.InitialLeaseTime = TimeSpan.FromMinutes(1);
lease.SponsorshipTimeout = TimeSpan.FromMinutes(2);
lease.RenewOnCallTime = TimeSpan.FromSeconds(2);
}
return lease;
}
}

È possibile modificare le proprietà di lease solo quando un lease si trova nello stato iniziale. Normalmente l'implementazione di InitializeLifetimeService richiama il metodo corrispondente della classe base per recuperare il lease esistente per l'oggetto remoto. Se non è mai stato eseguito il marshalling su questo oggetto, il lease restituito è allo stato iniziale, quindi è possibile impostare le proprietà. Una volta eseguito il marshalling sull'oggetto, il lease passa dallo stato iniziale allo stato attivo e qualsiasi tentativo di inizializzare le proprietà di lease verrà ignorato (viene lanciata un'eccezione). All'attivazione dell'oggetto remoto viene richiamato InitializeLifetimeService. All'attivazione della chiamata è possibile avere un elenco degli sponsor del lease e aggiungere altri nomi di sponsor in qualsiasi momento, mentre il lease è attivo.

I tempi di lease possono essere estesi in base a quanto riportato di seguito:

  • Un client può richiamare il metodo Renew sulla classe Lease.

  • Il lease può richiedere un Renewal dallo sponsor.

  • Quando un client richiama un metodo per l'oggetto, il lease viene rinnovato automaticamente con il valore RenewOnCall.

Quando un lease scade, il suo stato interno passa da Active a Expired, non vengono eseguite altre chiamate agli sponsor e l'oggetto viene sottoposto a garbage collection. Poiché è spesso difficile richiamare uno sponsor per gli oggetti remoti, se lo sponsor viene pubblicato sul Web o è protetto da un firewall, non deve necessariamente trovarsi nella stessa posizione del client; è sufficiente che sia in un punto della rete raggiungibile dall'oggetto remoto.

L'utilizzo dei lease per gestire la durata degli oggetti remoti è un metodo alternativo per il conteggio, che in genere è complesso e inefficace per le connessioni di rete non affidabili. Anche se può sembrare che la durata di un oggetto remoto venga estesa più del necessario, la riduzione del traffico di rete dovuto a questo conteggio e il ping dei client rende il leasing una soluzione molto attraente.

Esempio di remoting con un canale TCP

Questa appendice indica come scrivere un'applicazione remota semplice "Hello World". Il client passa una stringa all'oggetto remoto, che allega le parole "Hi There" alla stringa e riporta il risultato al client.

Questo codice deve essere salvato come server.cs. Di seguito è riportato il codice per il server:

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

namespace RemotingSamples {
  public class Sample {

    public static int Main(string [] args) {
      // Crea e registra un nuovo canale Tcp
      TcpChannel chan = new TcpChannel(8085);
      ChannelServices.RegisterChannel(chan);
      // Il metodo RegisterWellKnownServiceType permette di registrare l'oggetto per la     
      // futura attivazione [PARAMETRI (Tipo, URI, metodo di attivazione)]
      RemotingConfiguration.RegisterWellKnownServiceType
      (Type.GetType("RemotingSamples.HelloServer,object"), 
      "SayHello", WellKnownObjectMode.SingleCall);
      System.Console.WriteLine("Hit  to exit...");
      System.Console.ReadLine();
      return 0;
    }
  }
}

Questo codice deve essere salvato come client.cs:

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

namespace RemotingSamples {
  public class Client
  {
    public static int Main(string [] args)
    {
      TcpChannel chan = new TcpChannel();
      ChannelServices.RegisterChannel(chan);
      HelloServer obj = 
   (HelloServer)Activator.GetObject(typeof(RemotingSamples.HelloServer)
   , "tcp://localhost:8085/SayHello");
      if (obj == null) 
      System.Console.WriteLine("Could not locate server");
      else Console.WriteLine(obj.HelloMethod("Carlo"));
      return 0;
    } 
  }
}

Questo codice deve essere salvato come object.cs:

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

namespace RemotingSamples {
  public class HelloServer : MarshalByRefObject {

    public HelloServer() {
      Console.WriteLine("HelloServer activated");
    }

    public String HelloMethod(String name) {
      Console.WriteLine("Hello.HelloMethod : {0}", name);
      return "Hi there " + name;
    }
  }
}

Questo è il makefile:

all: object.dll server.exe client.exe

object.dll: share.cs
   csc /debug+ /target:library /out:object.dll object.cs

server.exe: server.cs
   csc /debug+ /r:object.dll /r:System.Runtime.Remoting.dll server.cs

client.exe: client.cs server.exe
   csc /debug+ /r:object.dll /r:server.exe /r:System.Runtime.Remoting.dll client.cs

E questi i risultati!:

Fonti:

MSDN

.::^top^::.

(2002) A cura di Carlo Becchi