Remoting Example: Tracking Service

The TrackingServices class provides for a general tracking service with pluggable tracking handlers. Methods on the ITrackingHandler interface are called under the following circumstances:

  • An ObjRef object has been generated (as the result of a marshal).
  • An ObjRef has been received (as the result of an unmarshal).
  • An object has been disconnected.

For more details, see TrackingServices and ITrackingHandler in the reference documentation.

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

  1. Type the following commands at a command prompt:

    [C#]

    csc /t:library TrackingHandler.cs

    csc /r:System.Runtime.Remoting.dll /t:library /out:ServiceClass.dll serviceclass.cs

    csc /r:System.Runtime.Remoting.dll /r:ServiceClass.dll client.cs

    csc /r:System.Runtime.Remoting.dll /r:TrackingHandler.dll /r:ServiceClass.dll server.cs

  2. Open two command prompts pointing to the same directory. In one, type server. In the other, type client.

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.

TrackingHandler.cs

using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Services;

public class TrackingHandler : ITrackingHandler{

   // Notifies a handler that an object has been marshaled.
   public void MarshaledObject(Object obj, ObjRef or){
      Console.WriteLine("Tracking: An instance of {0} was marshaled. The instance HashCode is: {1}", obj.ToString(), obj.GetHashCode().ToString());
      Console.WriteLine("ObjRef dump:");
      if (or.ChannelInfo != null){
         Console.WriteLine("  -- ChannelInfo: ");
         DumpChannelInfo(or.ChannelInfo);
      }
      if (or.EnvoyInfo != null)
         Console.WriteLine("  -- EnvoyInfo: " + or.EnvoyInfo.ToString());
      if (or.TypeInfo != null){
         Console.WriteLine("  -- TypeInfo: " + or.TypeInfo.ToString());
         Console.WriteLine("      -- " + or.TypeInfo.TypeName);
      }
      if (or.URI != null)
         Console.WriteLine("  -- URI: " + or.URI.ToString());
   }

   private void DumpChannelInfo(IChannelInfo info){

      foreach(object obj in info.ChannelData){
         if(obj is ChannelDataStore){
            foreach(string uri in ((ChannelDataStore)obj).ChannelUris)
               Console.WriteLine("      -- ChannelUris:" + uri);
         }
      }
   }

   // Notifies a handler that an object has been unmarshaled.
   public void UnmarshaledObject(Object obj, ObjRef or){
   Console.WriteLine("Tracking: An instance of {0} was unmarshaled. The instance HashCode is: {1}", obj.ToString(), obj.GetHashCode().ToString());
   }

   // Notifies a handler that an object has been disconnected.
   public void DisconnectedObject(Object obj){
   Console.WriteLine("Tracking: An instance of {0} was disconnected. The instance HashCode is: {1}", obj.ToString(), obj.GetHashCode().ToString());
   }
}

Server.cs

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

public class ServerProcess{

   public static void Main(string[] Args){

      TcpChannel channel = new TcpChannel(8080);
      ChannelServices.RegisterChannel(channel);

      TrackingServices.RegisterTrackingHandler(new TrackingHandler());

      ServiceClass service  = new ServiceClass();
      ObjRef obj = RemotingServices.Marshal(service,"TcpService");

      Console.WriteLine("\r\nPress Enter to unmarshal the object.");
      Console.ReadLine();

      RemotingServices.Unmarshal(obj);

      Console.WriteLine("Press Enter to disconnect the object.");
      Console.ReadLine();

      RemotingServices.Disconnect(service);
   }
}

Client.cs

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

public class ClientProcess{

   public static void Main(string[] Args){

      ChannelServices.RegisterChannel(new TcpChannel());

      WellKnownClientTypeEntry remotetype = new WellKnownClientTypeEntry(typeof(ServiceClass),"tcp://localhost:8080/TcpService");
      RemotingConfiguration.RegisterWellKnownClientType(remotetype);

      ServiceClass service = new ServiceClass(); 
      Console.WriteLine("Server time is: " + service.GetServerTime().ToLongTimeString());

   }
}

ServiceClass.cs

using System;
using System.Diagnostics;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;

public class ServiceClass : MarshalByRefObject{

   private DateTime starttime;

   public ServiceClass(){
      Console.WriteLine("A ServiceClass has been created.");
      starttime = DateTime.Now;
   }

   ~ServiceClass(){
      Console.WriteLine("ServiceClass being collected after " + (new TimeSpan(DateTime.Now.Ticks - starttime.Ticks)).ToString() + " seconds.");
    
   }

   public DateTime GetServerTime(){
      Console.WriteLine("Time requested by client.");
      return DateTime.Now;
   }
}

See Also

Remoting Examples | ITrackingHandler | TrackingServices