Remote Objects, Clients, and Servers

 
Chapter 21 - Distributed Applications with .NET Remoting
bySimon Robinsonet al.
Wrox Press 2002
  

Remote Objects, Clients , and Servers

Before we step into the details of the .NET Remoting architecture, let's look briefly at a remote object and a very small, simple client-server application that uses this remote object. After that, we will look in more detail at all the required steps and options.

The remote object we implement is called Hello . HelloServer is the main class of the application on the server, and HelloClient is for the client:

click to expand

Remote Objects

Remote objects are needed for distributed computing. An object that should be called remotely from a different system must be derived from System.MarshalByRefObject . MarshalByRefObject objects are confined to the application domain in which they were created. This means that they are never passed across application domains; instead a proxy object is used to access the remote object from another application domain. The other application domain can live inside the same process, in another process, or on another system.

A remote object has distributed identity . Because of this, a reference to the object can be passed to other clients, and they will still access the same object. The proxy knows about the identity of the remote object.

The MarshalByRefObject class has, in addition to the inherited methods from the Object class, methods to initialize and get the lifetime services. The lifetime services define how long the remote object lives. Lifetime services and the leasing features will be dealt with later in this chapter.

To see .NET Remoting in action, we will begin with a simple Class Library to create a remote object. The class Hello derives from System.MarshalByRefObject . In the constructor and destructor, a message is written to the console so that we know about the object's lifetime. In addition, we have just a single method, Greeting() , that will be called from the client.

In order to easily distinguish between the assembly and the class in the following sections, we have given them different names in the arguments of the method calls used. The name of the assembly is RemoteHello , and the class is named Hello .

   using System;     namespace Wrox.ProCSharp.Remoting     {     public class Hello : System.MarshalByRefObject     {     public Hello()     {     Console.WriteLine("Constructor called");     }     ~Hello()     {     Console.WriteLine("Destructor called");     }     public string Greeting(string name)     {     Console.WriteLine("Greeting called");     return "Hello, " + name;     }     }     }   

A Simple Server

For the server we create a new C# console application HelloServer . To use the TcpServerChannel class, we have to reference the System.Runtime.Remoting assembly. It's also required that we reference the RemoteHello assembly that we created earlier.

In the Main() method a System.Runtime.Remoting.Channels.Tcp.TcpServerChannel is created with the port number 8086 . This channel is registered with the System.Runtime.Remoting.Channels.ChannelServices class to make it available for remote objects. The remote object type is registered using System.Runtime.Remoting.RemotingConfiguration.RegisterWellKnownServiceType . Here we specify the type of the class in the remote object, the URI that is used by the client, and a mode. The mode WellKnownObject.SingleCall means that a new instance is created for every method call; we do not hold state in the remote object.

.NET Remoting allows creating stateless and stateful remote objects. In our first example we use well-known single-call objects that don't hold state. The other object type is called client-activated . Client-activated objects hold state. Later in this chapter we look at the object activation sequence, and go into more detail about these differences, and how these object types can be used.

After registration of the remote object, we keep the server running until a key is pressed:

   using System;     using System.Runtime.Remoting;     using System.Runtime.Remoting.Channels;     using System.Runtime.Remoting.Channels.Tcp;     namespace Wrox.ProCSharp.Remoting     {     public class HelloServer     {     [STAThread]     public static void Main(string[] args)     {     TcpServerChannel channel = new TcpServerChannel(8086);     ChannelServices.RegisterChannel(channel);     RemotingConfiguration.RegisterWellKnownServiceType(     typeof(Hello), "Hi",     WellKnownObjectMode.SingleCall);     System.Console.WriteLine("hit to exit");     System.Console.ReadLine();     }     }     }   

A Simple Client

The client is again a C# console application: HelloClient . Here the System.Runtime.Remoting assembly is also referenced so that we can use the TcpClientChannel class. In addition, we also have to reference our RemoteHello assembly. Although we will create the object on the remote server, we need the assembly on the client for the proxy to read the metadata during run time.

In the client program we're creating a TcpClientChannel object that's registered in ChannelServices . For the TcpChannel we are using the default constructor, so a free port is selected. Next the Activator class is used to return a proxy to the remote object. The proxy is of type System.Runtime.Remoting.Proxies.__TransparentProxy . This object looks like the real object. This is all achieved by reflection, where the metadata of the real object is read. The transparent proxy uses the real proxy to send messages to the channel:

   using System;     using System.Runtime.Remoting.Channels;     using System.Runtime.Remoting.Channels.Tcp;     namespace Wrox.ProCSharp.Remoting     {     public class HelloClient     {     [STAThread]     public static void Main(string[] args)     {     ChannelServices.RegisterChannel(new TcpClientChannel());     Hello obj = (Hello)Activator.GetObject(     typeof(Hello), "tcp://localhost:8086/Hi");     if (obj == null)     {     Console.WriteLine("could not locate server");     return;     }     for (int i=0; i< 5; i++)     {     Console.WriteLine(obj.Greeting("Christian"));     }     }     }     }   

When we start the server and the client program Hello, Christian appears five times in the client console. In the console window of the server application we see a similar output to this window:

click to expand

The first constructor is called the first time a method of the object is called remotely. Then for every method call a new instance gets created because we selected the WellKnownObjectMode.SingleCall activation mode. Depending on timing and resources needed, you may also see some destructor calls. If you start the client a few times you are sure to see some destructor calls.

  


Professional C#. 2nd Edition
Performance Consulting: A Practical Guide for HR and Learning Professionals
ISBN: 1576754359
EAN: 2147483647
Year: 2002
Pages: 244

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net