Esempio di .NET Remoting: pubblicazione dinamica
Questo argomento è specifico di una tecnologia legacy mantenuta per una questione di compatibilità con le applicazioni esistenti di versioni precedenti e non è consigliato per il nuovo sviluppo. Le applicazioni distribuite devono ora essere sviluppate utilizzando Windows Communication Foundation (WCF).
.NET Remoting supporta solo costruttori predefiniti con i tipi utilizzabili in remoto attivati dal server. Per pubblicare un oggetto dopo averlo creato con un costruttore specifico e avere il controllo completo sulla pubblicazione di quell'istanza specifica, è possibile pubblicare l'istanza a livello di codice.
Attenzione: |
---|
In .NET Remoting l'autenticazione o la crittografia non viene eseguita per impostazione predefinita. È pertanto consigliato che vengano effettuati tutti i passaggi necessari per verificare l'identità di client o server prima di interagirvi in modalità remota. Poiché le applicazioni .NET Remoting necessitano di autorizzazioni di tipo FullTrust, se si concede l'accesso al proprio server a un client non autorizzato, questi potrebbe eseguire codice come se fosse completamente attendibile. Autenticare sempre gli endpoint e crittografare i flussi di comunicazione. Per ulteriori informazioni, vedere Sicurezza in .NET Remoting. |
Per compilare ed eseguire l'esempio
Digitare i comandi seguenti 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
csc -t:library remote.cs csc -r:System.Runtime.Remoting.dll -r:remote.dll server.cs csc -r:System.Runtime.Remoting.dll -r:remote.dll client.cs
Aprire due prompt dei comandi che puntino alla stessa directory. In uno dei prompt, digitare server. Nell'altro, digitare client.
Per interrompere la pubblicazione dell'oggetto utilizzabile in remoto in più fasi, premere INVIO al prompt dei comandi ed eseguire nuovamente il client per osservare le diverse eccezioni generate per le diverse fasi. L'applicazione viene eseguita su un solo computer o in una rete. Per eseguire questa applicazione su una rete, sarà necessario sostituire "localhost" nella configurazione client con il nome del computer remoto.
Remote
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
using System;
using System.Collections.Generic;
using System.Text;
namespace Remote
{
public class ServiceClass : MarshalByRefObject
{
private DateTime m_startTime;
public ServiceClass()
{
Console.WriteLine("ServiceClass created without constructor. Instance hash is " + GetHashCode().ToString());
m_startTime = DateTime.Now;
}
~ServiceClass()
{
Console.WriteLine("I'm being collected after " + (new TimeSpan(DateTime.Now.Ticks - m_startTime.Ticks)).ToString() + " seconds.");
}
public DateTime GetServerTime()
{
Console.WriteLine("Time requested by a client.");
return DateTime.Now;
}
public int InstanceHash
{
get { return GetHashCode(); }
}
}
}
Server
Imports System
Imports System.Runtime.Remoting
Imports System.Runtime.Remoting.Channels
Imports System.Runtime.Remoting.Channels.Http
Module Module1
Sub Main()
Dim channel As New HttpChannel(8080)
ChannelServices.RegisterChannel(channel, False)
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 Module
using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Http;
using Remote;
namespace Server
{
class Server
{
static void Main(string[] args)
{
HttpChannel channel = new HttpChannel(8080);
ChannelServices.RegisterChannel(channel, false);
ServiceClass object1 = new ServiceClass();
// Creates the single instance of ServiceClass. All clients
// will use this instance.
ObjRef ref1 = 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();
}
}
}
Client
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, False)
' 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
End Class
using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.Remoting.Channels.Http;
using Remote;
namespace Client
{
public class ClientProcess
{
[MTAThread]
public static void Main(string[] args)
{
HttpChannel channel = new HttpChannel();
ChannelServices.RegisterChannel(channel, false);
// Registers the remote class. (This could be done with a
// configuration file instead of a direct call.)
RemotingConfiguration.RegisterWellKnownClientType(
Type.GetType("Remote.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.
ServiceClass object1 = new ServiceClass();
try
{
Console.WriteLine("ServerTime: " + object1.GetServerTime());
}
catch (Exception ex)
{
Console.WriteLine("Exception of type: " + ex.ToString() + " occurred.");
Console.WriteLine("Details: " + ex.Message);
}
}
}
}
Vedere anche
Riferimento
RemotingServices.Marshal Method
RemotingServices.Disconnect Method
ChannelServices.UnregisterChannel Method