Anda di halaman 1dari 11

Distributed Application in C# (.

NET
Remoting)
Introduction
.NET Remoting is a mechanism for communicating between objects which are not in the
same process. It is a generic system for different applications to communicate with one
another. The applications can be located on the same computer, different computers on the
same network, or on computers across separate networks.
Microsoft .NET Remoting provides a framework that allows objects to interact with each
other across application domains. Remoting was designed in such a way that it hides the
most difficult aspects like managing connections, marshaling data, and reading and writing
XML and SOAP. The framework provides a number of services, including object activation
and object lifetime support, as well as communication channels which are responsible for
transporting messages to and from remote applications.

Remote Objects
Any object outside the application domain of the caller should be considered remote, even if
the objects are executing on the same machine. Inside the application domain, all objects
are passed by reference while primitive data types are passed by value. Since local object
references are only valid inside the application domain where they are created, they cannot
be passed to or returned from remote method calls in that form. All local objects that have
to cross the application domain boundary have to be passed by value and should be
marked with the [serializable] custom attribute, or they have to implement the
ISerializable interface. When the object is passed as a parameter, the framework
serializes the object and transports it to the destination application domain, where the
object will be reconstructed. Local objects that cannot be serialized cannot be passed to a
different application domain and are therefore nonremotable.
Any object can be changed into a remote object by deriving it from
MarshalByRefObject(Enables access to objects across application domain boundaries in
applications that support remoting). When a client activates a remote object, it receives a
proxy to the remote object. All operations on this proxy are appropriately indirected to
enable the Remoting infrastructure to intercept and forward the calls appropriately.
In computer science, marshalling or marshaling is the process of transforming the
memory representation of an object to a data format suitable for storage or transmission,
and it is typically used when data must be moved between different parts of a computer
program or from one program to another.
In computer science, in the context of data storage, serialization is the process of
translating data structures or object state into a format that can be stored (for example, in
a file or memory buffer, or transmitted across a network connection link) and reconstructed
later in the same or another computer environment.
This process of serializing an object is also called marshalling an object.

Types of .NET Remotable Objects


There are three types of objects that can be configured to serve as .NET remote objects.

Single Call
Single Call objects service one and only one request coming in. Single Call objects are
useful in scenarios where the objects are required to do a finite amount of work. Single Call
objects are usually not required to store state information, and they cannot hold state
information between method calls.

Singleton Objects
Singleton objects are those objects that service multiple clients, and hence share data by
storing state information between client invocations.

Client-Activated Objects (CAO)


Client-activated objects (CAO) are server-side objects that are activated upon request from
the client. They can store state information between method calls for its specific client, and
not across different client objects.

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, it has to use
Remoting because the other application will have its own domain, and across domains,
object cannot communicate directly.

Contexts
The .NET runtime further divides the application domain into contexts. A context is a
boundary that contains objects that share common runtime properties. Access requests
must be marshaled across contexts.

Proxies
When a call is made between objects in the same Application Domain, only a normal local
call is required; however, a call across Application Domains requires a remote call. In order
to facilitate a remote call, a proxy is introduced by the .NET framework at the client side.
This proxy is an instance of the TransparentProxy class, directly available to the client to
communicate with the remote object. Generally, a proxy object is an object that acts in
place of some other object. The proxy object ensures that all calls made on the proxy are
forwarded to the correct remote object instance. In .NET Remoting, the proxy manages the
marshaling process and the other tasks required to make cross-boundary calls. The .NET
Remoting infrastructure automatically handles the creation and management of proxies.

RealProxy and TransparentProxy


The .NET Remoting Framework uses two proxy objects to accomplish its work of making a
remote call from a client object to a remote server object: a RealProxy object and a
TransparentProxy object. The RealProxy object does the work of actually sending messages
to the remote object and receiving response messages from the remote object. The
TransparentProxy interacts with the client, and does the work of intercepting the remote
method call made by the client.

Marshalling
Object Marshalling specifies how a remote object is exposed to the client application. It is
the process of packaging an object access request in one application domain and passing
that request to another domain. The .NET Remoting infrastructure manages the entire
marshaling process. There are two methods by which a remote object can be made
available to a local client object: Marshal by value, and Marshal by reference.

Marshalling objects by value


Marshal by value copies the entire object across application domain boundaries. The server creates a copy

of the object and passes the copy to the client. Marshal by value classes must either be
marked with the [Serilaizable] attribute in order to use the default serialization, or must
implement the ISerializable interface.

Marshalling objects by reference


With MarshalByRefObject, you are effectively sharing the object between the domains as a
reference. Marshal by reference classes must inherit from System.MarshalByRefObject.
Marshalling is done by the .NET Framework itself. We dont have to write any code for it.

Channels
The .NET Remoting infrastructure provides a mechanism by which a stream of bytes is sent
from one point to the other (client to server etc.). This is achieved via a channel. Strictly
speaking, it is a class that implements the IChannel interface. There are two pre-defined
.NET Remoting channels existing in System.Runtime.Remoting.Channels, the TcpChannel
and the HttpChannel. To use the TcpChannel, the server must instantiate and register the
TcpServerChannel class, and the client, the TcpClientChannel class.
Channel selection is subject to the following rules:

At least one channel must be registered with the remoting framework before a
remote object can be called. Channels must be registered before objects are
registered.
Channels are registered per application domain. There can be multiple application
domains in a single process. When a process dies, all channels that it registers are
automatically destroyed.
It is illegal to register the same channel that listens on the same port more than
once. Even though channels are registered per application domain, different
application domains on the same machine cannot register the same channel listening
on the same port. You can register the same channel listening on two different ports
for an application domain.
Clients can communicate with a remote object using any registered channel. The
remoting framework ensures that the remote object is connected to the right channel
when a client attempts to connect to it. The client is responsible for calling the
RegisterChannel on the ChannelService class before attempting to communicate with
a remote object.

Serialization Formatters
.NET Remoting uses serialization to copy marshal-by-value objects, and to send reference of
objects which are marshal-by-reference, between application domains. The .NET Framework
supports two kinds of serialization: binary serialization and XML serialization.

Formatters are used for encoding and decoding the messages before they are transported
by the channel. There are two native formatters in the .NET runtime, namely binary
(System.Runtime.Serialization.Formatters.Binary) and SOAP
(System.Runtime.Serialization.Formatters.Soap). Applications can use binary encoding
where performance is critical, or XML encoding where interoperability with other remoting
frameworks is essential.

.NET Remoting Metadata


.NET Remoting uses metadata to dynamically create proxy objects. The proxy objects that
are created at the client side have the same members as the original class. But the
implementation of the proxy object just forwards all requests through the .NET Remoting
runtime to the original object. The serialization formatter uses metadata to convert method
calls to payload stream and back.
The client can obtain the metadata information required to access the remote object in the
following ways:

The .NET assembly of the server object.


The Remoting object can provide a WSDL (Web Services Description Language) file
that describes the object and its methods.
.NET clients can use the SOAPSUDS utility to download the XML schema from the
server (generated on the server) to generate source files or an assembly that
contains only metadata, no code.

Object Activation
Object activation refers to the various ways in which a remote object can be instantiated.
Marshal by value objects have a simple activation scheme, they are created when the client
first requests them. Marshal by reference objects have two activation schemes:

Server Activated Objects


Server Activated Objects are created only when the client makes the first call to the remote
method. In other words, when the client asks for the creation of the remote object, only the
local proxy is created on the client, the actual remote object on the server is instantiated on
the first method call. These proxies can be generated as:
For Server Activated Objects, the proxy object (on the client) and the actual object (on the
server) are created at different times.

Client Activated Objects


These are created on the server immediately upon the client's request. An instance of a
Client Activated Object is created every time the client instantiates one, either by the use of
new or Activator.CreateInstance(...).

Object Lifetime and Leases


A Server Activated Object that has been registered as SingelCall has a very simple and
limited lifetime. It lives for a single call only. Thereafter, it is marked for removal by the
Garbage Collector.
The other two types, Singleton and Client Activated Objects, have their lifetimes managed
by a service introduced by the .NET Framework, the Leased Based Manager. On the server,
the application domain's lease manager determines when a server-side object should be

marked for deletion. Each application domain has its own lease manager object. For objects
that have object references that are transported outside the application, a lease is created.
The lease has a lease time; when the lease reaches zero, it expires, and the object is
disconnected from the .NET Remoting Framework. Once all the references to the object
within the AppDomain have been freed, the object will be collected when the next garbage
collection occurs. A sponsor is another object that plays a role in the life time. When a lease
has expired, one or more of the lease's sponsors are invoked by the Lease Manager, where
they are given the opportunity to renew the lease. If none of the sponsors decides to renew
the lease, the lease manager removes the lease and the object is garbage collected.

Renewing Leases (Increasing Life Times)


While objects have a default lease period, there are many ways to extend the lease period to
keep the object alive, in case the client wants to maintain state in the same server object.
Once the object has been marshaled, the lease goes from the initial to the active state, and any
attempt to initialize the lease properties will be ignored (an exception is thrown).
InitializeLifetimeService is called when the remote object is activated. After activation, the
lease can only be renewed.
The .NET Remoting implementation gives you two ways to renew the lease on a remote object.
The client can call ILease.Renew directly, or the client can contact a sponsor and ask the
sponsor to renew the lease.
The sponsor object listens for queries from the host system's lease manager, and responds
accordingly. Sponsors register with the lease manager by obtaining a reference to the lease and
calling ILease.Register. The lease manager will periodically query the sponsor to see if it wants
to renew the lease. If the sponsor wants to renew the lease, it returns a renewal TimeSpan
value in response to the server's query.
Sponsors are preferable to client ILease.Renew loops, for several reasons. First, the server's
lease manager keeps track of when the object's lease is about to expire, and will query the
sponsor as needed in order to ensure the opportunity to extend the lease before time runs out.
It also is more efficient, both in bandwidth and processing time. In general, where there are
multiple clients for a single remote object (as in the case of a singleton), it is more efficient for
the lease manager to query a single object for renewal rather than to have each client
continually pinging the server. This is also true in the case of client activated objects because it
reduces the network traffic to just the minimum required to keep the object alive.
You can have the client itself implement the Isponsor interface, or you can create a sponsor
object that maintains leases for one or more remote objects and clients. Here, I am specifying
the code to implement Isponsor by the client itself.
Implement the Isponsor in the remotable client class:
class RemoteClient: System.MarshalByRefObject, Isponsor

The Isponsor interface requires that you implement a single method, Renewal. The return value
is the amount of time, expressed as a TimeSpan, to extend the lease. Our Renewal method will
extend the lease for an additional 30 seconds. Here's the code, which you should add to the
remote client:
public TimeSpan Renewal (ILease lease)

{
return TimeSpan.FromSeconds(30);
}

Finally, register the RemoteClient object with the server's lease manager. Insert the code below
where the server's object instance is being created:
// Instantiate the object
RemoteableClass MyRemotObject = new RemoteableClass();
// register as a sponsor
ILease lease = (ILease)RemotingServices.GetLifetimeService(MyRemotObject);
lease.Register(this);

How to Implement Remoting


In the following discussion, we will discuss how we can implement remoting in our applications.
The code given in the discussion is just to show what is necessary in the code. You can get the
whole code from the source code files.

Create a Remotable Object


A remotable object is an object that inherits from MarshalByRefObject.
Create a new C# class library project. Add a class called MyRemotableObject, and put in the
following code. Add a reference to System.Runtime.Remoting in the project, otherwise the
TcpChannel will not be found. Compile the class to make sure you have everything correct.
MyRemotableObject.cs
namespace RemotableObjects
{
public class MyRemotableObject : MarshalByRefObject
{
public MyRemotableObject()
{
}
public void SetMessage(string message)
{
Cache.GetInstance().MessageString = message;
}
}
}

Create a Server to Expose the Remotable


Object
We need to create a server object that will act as a listener to accept remote object requests.
For this example, we will use the TCP/IP channel. We first create an instance of the channel, and
then register it for use by clients at a specific port. The service can be registered as
WellKnownObjectMode.SingleCall, which results in a new instance of the object for each client,
or as WellKnownObjectMode.Singleton, which results in one instance of the object used for all
clients.

It is not necessary to create the server listener if you are planning to use IIS. For obvious
reasons, IIS only supports the use of the HttpChannel. Create a virtual directory for your
application, and then put code to register your service in the Application_Start event.
For our example, we'll go ahead and create a server listener, in case you don't have IIS. Since
the service needs to be bound to an available port, for our example, I chose 8080, which is a
port that I know to be unused on my computer. You may need to choose a different port
depending upon what ports you have available. To see a list of the used ports on your computer,
open a command prompt, and issue the command "netstat --a". It may produce a long listing, so
make sure the command prompt buffer sizes are set to allow scrolling. Compile the class to
make sure you have everything correct.
Create a new C# Windows Application project. Add a Windows Form called frmRServer, and
paste in the following code. Add a reference to System.Runtime.Remoting in the project,
otherwise the TcpChannel will not be found. In addition, add a reference to the project
containing the MyRemotableObject, otherwise the code will not compile because it won't know
how to find a reference to MyRemotableObject. Here, I am giving a part of the code. You can
get the complete code from the source code files.
namespace RemotableObjects
{
public class frmRServer : System.Windows.Forms.Form, IObserver
{
private System.Windows.Forms.TextBox textBox1;
private MyRemotableObject remotableObject;
private System.ComponentModel.Container components = null;
public frmRServer()
{
InitializeComponent();
remotableObject = new MyRemotableObject();
// using TCP protocol
TcpChannel channel = new TcpChannel(8080);
ChannelServices.RegisterChannel(channel);
RemotingConfiguration.RegisterWellKnownServiceType(
typeof(MyRemotableObject),"HelloWorld",
WellKnownObjectMode.Singleton);
RemotableObjects.Cache.Attach(this);
}
}
}

Create a Client to Use the Remotable Object


The client will be very simple. It will connect to the server, create an instance of the object using
the server, and then execute the SetString method.
Create a new C# Windows Application project. Add a Windows Form called frmRCleint, and
paste in the following code. Add a reference to the project containing the SampleObject,
otherwise the code will not compile because it won't know how to find a reference to
SampleObject. Compile the class to make sure you have everything correct. Here, only part of
code is given just to show the concept. You can get whole code from the source given:
namespace RemotableObjects
{
public class frmRCleint : System.Windows.Forms.Form
{

private System.Windows.Forms.TextBox textBox1;


MyRemotableObject remoteObject;
private System.ComponentModel.Container components = null;
public frmRCleint()
{
InitializeComponent();
// using TCP protocol
// running both client and server on same machines
TcpChannel chan = new TcpChannel();
ChannelServices.RegisterChannel(chan);
// Create an instance of the remote object
remoteObject = (MyRemotableObject) Activator.GetObject(
typeof(MyRemotableObject),"tcp://localhost:8080/HelloWorld");
}
private void textBox1_TextChanged(object sender, System.EventArgs e)
{
remoteObject.SetMessage(textBox1.Text);
}
}
}

Running the Application


To run the application, compile the Remoteable Object Project object. Compile server application
and run it. Compile the client application and run it. Two dialogue boxes will appear: one for the
Remoting server, and one for the Remoting client. The Remoting server will listen for the
requests. And the Remoting client is ready to pass the message to the server. Now, type any
string in the client dialogue box, and the client will send it to the server through Remoting, and
the server will display the string in the dialog box of the server application. This is a simple
demonstration of easy and understandable Remoting.

Object Configurations
There are two ways to configure remote objects. One is by code, and the other is by using a
configuration file, both on the server and the client. The advantage of using a configuration file
is we dont have to compile the code every time we change the configuration, so we can change
the configuration of the application at any time without disturbing the code or executables. By
convention, the configuration file name has the format executablename.config.

Configuration files
A typical configuration file includes the following, among other, information:

Host application information

Name of the objects

URI of the objects

Channels being registered (multiple channels can be registered at the same time)

Lease time information for the server objects


Here is an example the configuration filename:

Server remoting configuration (server.exe.config):


<configuration>
<system.runtime.remoting>
<application name="server">
<service>
<activated type="remote.ServiceClass, remote"/>
</service>
<channels>
<channel ref="http" port="8080">
<serverProviders>
<formatter ref="binary" typeFilterLevel="Full"/>
</serverProviders>
<clientProviders>
<formatter ref="binary"/>
</clientProviders>
</channel>
</channels>
</application>
</system.runtime.remoting>
</configuration>

Client remoting configuration (client.exe.config)


<configuration>
<system.runtime.remoting>
<application name="client">
<client url = "http://localhost:8080">
<activated type="remote.ServiceClass, remote"/>
</client>
<channels>
<channel ref="http" port="0">
<serverProviders>
<formatter ref="binary" typeFilterLevel="Full"/>
</serverProviders>
<clientProviders>
<formatter ref="binary"/>
</clientProviders>
</channel>
</channels>
</application>
</system.runtime.remoting>
</configuration>

To use these configuration files in our Remoting test application, place those files (server.config
and client.config) in the directory that contains the server.exe and client.exe programs.
Using application configuration files greatly simplifies the code required to set up a remoting
application. For example, the single line shown here takes the place of all the configuration code
in the server.cs program's Main method:
RemotingConfiguration.Configure("server.config");

The configuration files shown set the client activation--each client gets its own object. If you
want to configure for Singleton mode, change the <service> section of the server's
configuration file so that it reads:
<service>

<wellknown
type="remote.ServiceClass, remote"
objectUri="ServiceURI"
mode="Singleton"
/>
</service>

And change the <client> section of the client's configuration file so that it reads:
<client url = "http://localhost:8080">
<wellknown
type="remote.ServiceClass, remote"
url="http://localhost:8080/ServiceURI"
/>
</client>

Configuration through code


Server
TcpServerChannel channel = new TcpServerChannel(rs.mPort);
ChannelServices.RegisterChannel(channel);
RemotingConfiguration.RegisterWellKnownServiceType(
typeof(RemoteServerObject), "Test",
WellKnownObjectMode.SingleCall);

Client
TcpClientChannel chan = new TcpClientChannel();
ChannelServices.RegisterChannel(chan);
IRemoteCom obj = (IRemoteCom)Activator.GetObject(typeof(IRemoteCom),
"tcp://localhost:1002/Test");

Hosting .NET Remoting Objects


.NET Remoting objects can be hosted in:

Managed executables
NET Remoting objects can be hosted in any regular .NET EXE or a managed service.

IIS
Remoting objects can be hosted in the Internet Information Server (IIS). By default, Remoting
objects hosted in IIS receive messages through the HTTP channel. For hosting Remoting objects
under the IIS, a virtual root has to be created, and a "remoting.config" file has to be copied to it.
The executable or DLL containing the remote object should be placed in the bin directory under
the directory the IIS root points to. It is important to note that the IIS root name should be the
same as the application name specified in the configuration files. The Remoting configuration
file is automatically loaded when the first message arrives in the application.

.NET Component Services


NET Remoting objects can be hosted in the .NET component services infrastructure to take
advantage of the various COM+ services like Transactions, JIT, and Object pooling.

MyRemotableObject remoteObject;
private System.ComponentModel.Container components = null;
public frmRCleint()
{
InitializeComponent();
// using TCP protocol
// running both client and server on same machines
TcpChannel chan = new TcpChannel();
ChannelServices.RegisterChannel(chan);
// Create an instance of the remote object
remoteObject = (MyRemotableObject) Activator.GetObject(
typeof(MyRemotableObject),"tcp://localhost:8080/HelloWorld");
}
private void textBox1_TextChanged(object sender, System.EventArgs e)
{
remoteObject.SetMessage(textBox1.Text);
}

Running the Application


To run the application, compile the Remotable Object Project object. Compile the server
application and run it. Compile the client application and run it. Two dialog boxes will appear,
one for the Remoting server and one for the Remoting client. The Remoting server will listen for
the requests. And the Remoting client is ready to pass the message to the server. Now, type in
any string in the client dialog box, and the client will send it to the server through Remoting, and
the server will display the string in the dialog box of the server application. This is a simple
demonstration of easy and understandable Remoting.

Anda mungkin juga menyukai