Remoting Example: Dynamic Publication
.NET remoting supports only default constructors with server-activated remotable types. If you want to publish an object after creating it with some specific constructor and have complete control over the publication of that specific instance, you can publish your instance programmatically.
CAUTION .NET remoting does not do authentication or encryption by default. Therefore, it is recommended that you take all necessary steps to make certain of the identity of clients or servers before interacting with them remotely. Because .NET remoting applications require FullTrust permissions to execute, if a unauthorized client were granted access on your server, the client could execute code as though it were fully trusted. Always authenticate your endpoints and encrypt the communication streams, either by hosting your remoted types in Internet Information Services (IIS), or by building a custom channel sink pair to do this work.
To compile and run this sample
- Type the following commands at the command prompt:
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
- Open two command prompts pointing to the same directory. In one, type server. In the other, type client.
To stop publishing the remotable object in stages, press ENTER at the server command prompt, and rerun the client to observe the different exceptions thrown for the different stages. This application runs on a single computer or across a network. If you want to run this application over a network, you must replace "localhost" in the client configuration with the name of the remote computer.
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
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
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"), "http://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