|
The C# Column
Remoting Basics - I
Unless you have spent the last two years in hibernation, you
must already be aware of XML Web Services and its powers. Despite all the attention
Web Services have received as an ultimate solution to distributed computing,
let us face the ground reality. There are still thousands of applications running
on intranets and there would be thousands more that would be developed in future.
The goal of these applications is not to carry out cross–platform
communication across heterogeneous systems (which is the strength of Web Services).
In such cases there is no point in building these applications as Web Services
as they may not be able to provide the desired performance and capabilities.
Instead using .NET Remoting to carry out client–server communication would
be an excellent solution.
Why .NET Remoting
Unlike the loosely coupled applications that rely on protocols
and standards like HTTP, SOAP and XML, the tightly coupled applications do not
have to necessarily rely on universally available protocols and standards. Though
.NET Remoting can be used for cross–platform communication, it is optimised
for communication between .NET centric applications. Before advent of .NET DCOM
(Distributed Component Object Model) was the underlying technology used for
remote communication between Windows-based applications. However, DCOM was based
on a proprietary protocol and suffered from disadvantages like difficult setup
and configuration process, possibility of firewalls denying the request for
communication and a difficult learning curve. All these limitations have been
fixed up in .NET Remoting.
Before taking a look at the .NET Remoting architecture we
must know what application domains are, because remoting is all about communicating
between application domains in same/different processes.
Application Domains
In .NET when an application is loaded in memory a process
is created and within this process an application domain is created. The application
is actually loaded in the application domain. If this application communicates
with another application, .NET loads the other application in a different application
domain. This application domain may belong either to the same process or to
a different process.
Thus one process can host multiple application domains. If
loaded in the same process then the communication between the two applications
is more efficient because the overheads involved in inter-application domain
communication are less as compared to inter–process communication.
In
Remoting the communication happens between two application domains running in
same or different processes on physically same or different machines connected
to an intranet or internet.
.NET Remoting Basics
A conventional class can be accessed only by clients running
in the same application domain in which the class is loaded. At the core of
.NET Remoting lies a ‘Remotable Class’. This class is loaded in
a server application domain. The remotable class is a class that can be used
by clients running in separate application domains than server application domain.
To interact or communicate with the object of the remotable
class, the client needs a ‘Channel’ and a ‘Proxy’. The
Channel connects the server application domain and the client application domain.
It physically moves bytes from one application domain to another. The proxy
looks and feels like the real object, however it merely holds a reference to
the remotable object. All the calls that the client wishes to place on the remotable
object are placed on the proxy and these calls are then transmitted to the remotable
object through the channel. The following figure shows the .NET Remoting Architecture:
Now let us understand the .NET Remoting architecture by building
a simple application.
In this application we have built a server and a client.
Here the client will activate an object present in the server’s application
domain and call methods on it. For this we have created a remotable class called
User consisting of a method called getuser( ) that simply returns the name of
a user currently logged on the machine.
As the remotable class is loaded in the server application
domain, the getuser( ) method would always return the name of the user logged
on the machine where server is running.
We have built the application in three parts—a class
library consisting of the remotable class, a server as console application and
client also as a console application. Let us take a look at them one by one.
The Remotable Class
Here we have created a ‘Class Library’ project
and named it as UserLib. In this project we have created a class called User
and added a method called getuser( ) to it. To make this class a remotable class,
all we need to do is derive it from System.MarshalByRef class. The User class
is shown below:
using System ;
namespace UserLib
{
public class User : MarshalByRefObject
{
public string getuser( )
{
return Environment.UserName ;
}
}
The Environment class consists of methods and properties
that provide information regarding the current environment of the machine and
the platform. UserName is a property of the Environment class that returns the
name of the user currently logged on the machine, as a string object. The getuser(
) method returns this string.
The Server
We need to do two things in the server—register the
remotable class and register a channel for communication. The server is required
to register a remotable class so that it can be activated from another application
domain. The server registers the remotable class by calling one of two shared
methods belonging to the System.Runtime.Remoting.RemotingConfiguration class.
The two methods are RegisterActivatedServiceType( ) and RegisterWellKnownServiceType(
). We will later see in detail what these methods mean and what is the difference
between them. For the time being it is enough to understand that these methods
register the remotable class. To create the server application we have created
a ‘Console Application’ and named it UserServer. The code in UserServer
is given below:
using System ;
using System.Runtime.Remoting ;
using System.Runtime.Remoting.Channels ;
using System.Runtime.Remoting.Channels.Tcp ;
using UserLib ;
namespace UserServer
{
class Class1
{
static void Main ( string[ ] args )
{
TcpServerChannel channel =
new TcpServerChannel ( 500 ) ;
ChannelServices.RegisterChannel ( channel ) ;
RemotingConfiguration.
RegisterWellKnownServiceType
( typeof ( User ) , “User”, WellKnownObjectMode.SingleCall ) ;
Console.WriteLine ( “Press Enter to terminate...” ) ;
Console.ReadLine( ) ;
}
}
}
Here we have used the RegisterWellKnownServiceType( ) method
for registering the remotable class. To this method we have first passed the
type of the remotable object. Type represents the RTTI (Run-time Type Information)
of a class. It can be obtained by using the typeof operator. The typeof operator
returns the Type object of the specified type. Next we passed the object URI.
The object URI will be used by the client to activate an instance of the remotable
class. The third parameter specifies the activation mode. We can specify one
of the two activation modes available—WellKnownObjectMode.SingleCall and
WellKnownObjectMode.Singleton. We will see the difference and use of these modes
later.
In the next statement we have created a TCP channel of type
TcpServerChannel with port as 500. The server would now listen at this port.
The channel accepts TCP connections from remote clients. This class falls under
the System.Runtime.Remoting.Channels.Tcp namespace. Next we have registered
the channel using the RegisterChannel( ) method, which is a shared method of
the ChannelServices class.
To get the information regarding the User class, we need
to add a reference to UserLib.dll.
(To be continued…)
|