Esempio di comunicazione remota: pubblicazione dinamica

In .NET Remoting vengono supportati solo i costruttori predefiniti con i tipi remotizzabili attivati da server. Se si desidera pubblicare un oggetto dopo averlo creato con un costruttore specifico e dopo aver completato il controllo sulla pubblicazione di tale specifica istanza, è possibile pubblicare l'istanza a livello di codice.

Attenzione   .NET Remoting non consente di effettuare l'autenticazione né la crittografia per impostazione predefinita. Si consiglia dunque di eseguire tutte le azioni necessarie per verificare l'identità dei client o dei server prima di interagire con essi in modalità remota. Poiché l'esecuzione delle applicazioni .NET Remoting richiede autorizzazioni FullTrust, qualora a un client non autorizzato venisse concesso l'accesso al server, il client potrebbe eseguire codice come se fosse completamente attendibile. È necessario autenticare sempre gli endpoint e crittografare i flussi di comunicazione mediante l'hosting dei tipi remoti in Internet Information Services (IIS) oppure generando a questo scopo una coppia di sink di canale personalizzata.

Per compilare ed eseguire l'esempio

  1. Digitare i seguenti comandi al prompt dei comandi:

    vbc -t:library remote.vb

    vbc -r:System.Runtime.Remoting.dll -r:remote.dll server.vb

    vbc -r:System.Runtime.Remoting.dll -r:remote.dll client.vb

  2. Aprire due prompt dei comandi che puntino alla stessa directory. In uno, digitare server e nell'altro client.

Per interrompere la pubblicazione dell'oggetto remotizzabile in più fasi, premere INVIO al prompt dei comandi del server ed eseguire nuovamente il client per osservare le diverse eccezioni generate per le diverse fasi. Questa applicazione viene eseguita su un singolo computer o in una rete. Per eseguire l'applicazione in una rete, nella configurazione del client è necessario sostituire hostlocale con il nome del computer remoto.

remote.vb

Imports System

Public Class ServiceClass
   Inherits MarshalByRefObject

   Private m_starttime As DateTime

   Public Sub New()
      Console.WriteLine("ServiceClass created without constructor. Instance hash is " & Me.GetHashCode().ToString())
      m_starttime = DateTime.Now
   End Sub   

   Overrides Protected Sub Finalize()
      Console.WriteLine("I'm being collected after " & (New TimeSpan(DateTime.Now.Ticks - m_starttime.Ticks)).ToString() & " seconds.")
      MyBase.Finalize()
   End Sub    

   Public Function GetServerTime() As DateTime
      Console.WriteLine("Time requested by a client.")
      Return DateTime.Now
   End Function   

   Public ReadOnly Property InstanceHash() As Integer
      Get
         Return Me.GetHashCode()
      End Get
   End Property 

End Class

Server.vb

Imports System
Imports System.Runtime.Remoting
Imports System.Runtime.Remoting.Channels
Imports System.Runtime.Remoting.Channels.Http

Public Class ServerProcess
   <MTAThread()> _
   Public Shared Sub Main()

      Dim channel As New HttpChannel(8080)
      ChannelServices.RegisterChannel(channel)

      Dim object1 As New ServiceClass()

      ' Creates the single instance of ServiceClass. All clients
      ' will use this instance.
      Dim ref1 As ObjRef = RemotingServices.Marshal(object1, "object1uri")
      Console.WriteLine("ObjRef.URI: " & ref1.URI)

      Console.WriteLine("Running. Press Enter to end publication.")
      Console.ReadLine()

      ' This unregisters the object from publication, but leaves
      ' the channel listening.
      RemotingServices.Disconnect(object1)
      Console.WriteLine()
      Console.WriteLine("Disconnected the object. Client now receives a RemotingException.")
      Console.WriteLine("Press Enter to unregister the channel.")
      Console.ReadLine()
      ' At this point, the ServerClass object still exists. The server
      ' could republish it.

      ' This unregisters the channel, but leaves the application 
      ' domain running.
      ChannelServices.UnregisterChannel(channel)
      Console.WriteLine("Unregistered the channel. Client now receives a WebException.")
      ' The ServerClass object still exists. The server could
      ' reregister the channel and republish the object.
      Console.WriteLine("The host application domain is still running. Press Enter to stop the process.")
      Console.ReadLine()

      ' The ServiceClass object's Finalize method writes a message to
      ' the console. A single object will almost always succeed in 
      ' running its Finalize method before the Console is finalized;
      ' in a larger application, you could ensure that all objects 
      ' finalize before the application ends by calling the garbage 
      ' collector and waiting.
      GC.Collect()
      GC.WaitForPendingFinalizers()
   End Sub
   
End Class

Client.vb

Imports System 
Imports System.Runtime.Remoting
Imports System.Runtime.Remoting.Channels
Imports System.Runtime.Remoting.Channels.Tcp
Imports System.Runtime.Remoting.Channels.Http

Public Class ClientProcess
   <MTAThread()> _
   Public Shared Sub Main()
      
      Dim channel As New HttpChannel(0)
      ChannelServices.RegisterChannel(channel)

      ' Registers the remote class. (This could be done with a
      ' configuration file instead of a direct call.)
      RemotingConfiguration.RegisterWellKnownClientType(Type.GetType("ServiceClass, remote"), "https://localhost:8080/object1uri")

      ' Instead of creating a new object, this obtains a reference
      ' to the server's single instance of the ServiceClass object.
      Dim object1 As ServiceClass = New ServiceClass()

      Try
         Console.WriteLine("ServerTime: " & object1.GetServerTime())
      Catch ex As Exception
         Console.WriteLine("Exception of type: " & ex.GetType.ToString & " occurred.")
         Console.WriteLine("Details: " & ex.Message)
      End Try

   End Sub     ' Main
End Class   ' ClientProcess

Vedere anche

Esempi di comunicazione remota | Metodo RemotingServices.Marshal | Metodo RemotingServices.Disconnect | Metodo ChannelServices.UnregisterChannel