Tuesday, April 1, 2008

Remoting

.NET Remoting

What is .NET Remoting?
.NET Remoting is an enabler for application communication. It is a generic system for different applications to use to communicate with one another. .NET objects are exposed to remote processes, thus allowing interprocess communication. The applications can be located on the same computer, different computers on the same network, or even computers across separate networks.
.NET Remoting versus Distributed COM
In the past interprocess communication between applications was handled through Distributed COM, or DCOM. DCOM works well and the performance is adequate when applications exist on computers of similar type on the same network. However, DCOM has its drawbacks in the Internet connected world. DCOM relies on a proprietary binary protocol that not all object models support, which hinders interoperability across platforms. In addition, have you tried to get DCOM to work through a firewall? DCOM wants to communicate over a range of ports that are typically blocked by firewalls. There are a ways to get it to work, but they either decrease the effectiveness of the firewall (why bother to even have the firewall if you open up a ton of ports on it), or require you to get a firewall that allows support for binary traffic over port 80.
.NET Remoting eliminates the difficulties of DCOM by supporting different transport protocol formats and communication protocols. This allows .NET Remoting to be adaptable to the network environment in which it is being used.
.NET Remoting versus Web Services
Unless you have been living in a cave, or are way behind in your reading, you have probably read something about Web services. When you read the description of .NET Remoting it may remind you a lot of what you're read about Web services. That is because Web services fall under the umbrella of .NET Remoting, but have a simplified programming model and are intended for a wide target audience.
Web services involve allowing applications to exchange messages in a way that is platform, object model, and programming language independent. Web services are stateless and know nothing about the client that is making the request. The clients communicate by transferring messages back and forth in a specific format known as the Simple Object Access Protocol, or SOAP. (Want to get some funny looks in the hallway? Stand around in the hallway near the marketing department with your colleagues and discuss the benefits of using SOAP).
The following list outlines some of the major differences between .NET Remoting and Web services that will help you to decide when to use one or the other:
· ASP.NET based Web services can only be accessed over HTTP. . NET Remoting can be used across any protocol.
· Web services work in a stateless environment where each request results in a new object created to service the request. .NET Remoting supports state management options and can correlate multiple calls from the same client and support callbacks.
· Web services serialize objects through XML contained in the SOAP messages and can thus only handle items that can be fully expressed in XML. .NET Remoting relies on the existence of the common language runtime assemblies that contain information about data types. This limits the information that must be passed about an object and allows objects to be passed by value or by reference.
· Web services support interoperability across platforms and are good for heterogeneous environments. .NET Remoting requires the clients be built using .NET, or another framework that supports .NET Remoting, which means a homogeneous environment.
Remoting Objects:
Remotable objects are objects that function well in a widely distributed environment. There are two main kinds of remotable objects:
· Marshal-by-value objects, which are copied and passed out of the application domain.
· Marshal-by-reference objects, for which a proxy is created and used by the client to access the object remotely.

Marshall – by – Value:
Marshal-by-value (MBV) objects declare their serialization rules (either by implementing ISerializable to implement their own serialization, or by being decorated with SerializableAttribute, which tells the system to serialize the object automatically) but do not extend MarshalByRefObject. The remoting system makes a complete copy of these objects and passes the copy to the calling application domain. Once the copy is in the caller's application domain, calls to the copy go directly to that copy. Further, MBV objects that are passed as arguments are also passed by value. Other than declaring the SerializableAttribute attribute or implementing ISerializable, you do not need to do anything to pass instances of your class by value across application or context boundaries.
Use MBV objects when it makes sense for performance or processing reasons to move the complete state of the object and any executable functionality to the target application domain. In many scenarios, this reduces lengthy, resource-consuming round trips across network, process, and application domain boundaries. MBV objects are also used directly from within the object's original application domain. In this case, because no marshaling takes place, no copy is made and access is very efficient.
On the other hand, if your published objects are very large, passing an entire copy around a busy network might not be the best choice for your application. In addition, no changes to the state of the copied object are ever communicated back to the original object in the originating application domain. At an abstract level, this scenario is similar to that of a static HTML page requested by a client browser. The server copies the file, writes it into a stream, sends it out, and forgets about it. Any subsequent request is merely another request for another copy.

Marshall – by – reference:
Marshal-by-reference (MBR) objects are remotable objects that extend at least System.MarshalByRefObject. Depending on what type of activation has been declared, when a client creates an instance of an MBR object in its own application domain, the .NET remoting infrastructure creates a proxy object in the caller's application domain that represents the MBR object, and returns to the caller a reference to that proxy. The client then makes calls on the proxy. Remoting marshals those calls, sends them back to the originating application domain, and invokes the call on the actual object.
Note If the client is in the same application domain as the MBR object, the infrastructure returns to the client a direct reference to the MBR object, avoiding the overhead of marshaling.
If a MarshalByRefObject is passed as a parameter, it becomes a proxy in the other application domain when the call arrives. MBR return values and out parameters work in the same way.
You should use MBR objects when the state of the object and any executable functionality should stay in the application domain in which it was created. For example, an object that has an internal field that is an operating system handle should extend MarshalByRefObject because the operating system handle would not be meaningful in another application domain, in another process, or on another computer. Sometimes an object can also be prohibitively large; that might work on a robust server, but not when sent over a wire to a 33.6 kbps modem.

Activatoin:

Client Activation:

Client-activated objects are objects whose lifetimes are controlled by the calling application domain, just as they would be if the object were local to the client. With client activation, a round trip to the server occurs when the client tries to create an instance of the server object, and the client proxy is created using an object reference (ObjRef) obtained on return from the creation of the remote object on the server. Each time a client creates an instance of a client-activated type, that instance will service only that particular reference in that particular client until its lease expires and its memory is recycled. If a calling application domain creates two new instances of the remote type, each of the client references will invoke only the particular instance in the server application domain from which the reference was returned.

To create an instance of a client-activated type, clients either configure their application programmatically (or using a configuration file) and call new (New in Visual Basic), or they pass the remote object's configuration in a call to Activator.CreateInstance. The following code example shows such a call, assuming a TcpChannel has been registered to listen on port 8080.

[Visual Basic]
Dim Object() = {New UrlAttribute("tcp://computername:8080/RemoteObjectApplicationName ")}
' Note that the second parameter (Nothing) specifies that no arguments
' are being passed.
Dim MyRemoteClass As RemoteObjectClass = _
CType( _
Activator.CreateInstance(GetType(RemoteObjectClass), Nothing, url), _
RemoteObjectClass)

[C#]
object[] url = {new UrlAttribute("tcp://computername:8080/RemoteObjectApplicationName")};
// Note that the second parameter (null) specifies that no arguments
// are being passed.
RemoteObjectClass MyRemoteClass = (RemoteObjectClass)Activator.CreateInstance(
typeof(RemoteObjectClass),
null,
url
);



Server Activation:

Server-activated objects are objects whose lifetimes are directly controlled by the server. The server application domain creates these objects only when the client makes a method call on the object, rather than when the client calls new (New() in Visual Basic) or Activator.GetObject; this saves a network round trip solely for the purpose of instance creation. Only a proxy is created in the client application domain when a client requests an instance of a server-activated type.

There are two activation modes (or WellKnownObjectMode values) for server-activated objects: Singleton and SingleCall.

Singleton types never have more than one instance at any one time. If an instance exists, all client requests are serviced by that instance. If an instance does not exist, the server creates an instance and all subsequent client requests will be serviced by that instance. Because Singleton types have an associated default lifetime, clients will not always receive a reference to the same instance of the remotable class, even if there is never more than one instance available at any one time.

SingleCall types always have one instance per client request. The next method invocation will be serviced by a different server instance, even if the previous instance has not yet been recycled by the system. SingleCall types do not participate in the lifetime lease system.

To create an instance of a server-activated type, clients either configure their application programmatically (or using a configuration file) and call new, or they pass the remote object's configuration in a call to Activator.GetObject.

The following code example shows a call to Activator.GetObject, assuming a TcpChannel has been registered to communicate on port 8080. If your client knows only that the server object implements a particular interface, you must use a call to Activator.GetObject, because you can only use new (New in Visual Basic) to create an instance of a class.

[Visual Basic]
Dim MyRemoteClass As RemoteObjectClass = _
CType( _
Activator.GetObject(_
GetType(RemoteObjectClass), _
"tcp://computername:8080/RemoteObjectUri" _
), _ RemoteObjectClass )

[C#]
RemoteObjectClass MyRemoteClass = (RemoteObjectClass)Activator.GetObject(
typeof(RemoteObjectClass),
"tcp://computername:8080/RemoteObjectUri ");

Remember, the preceding call does not create the remote object on the server. It returns to the client only a reference to the local proxy for the remote object. The client can now continue to treat MyRemoteClass as though it is a direct reference to the remote object. The instance that the client actually uses to communicate from method call to method call depends on whether the server object is declared as a Singleton or SingleCall type. Regardless of whether the publisher of the server object exposes this information, the client treats the object reference that it has exactly the same.

Leases:
Leases are created when an MBR object is activated in another application domain.
Whenever an MBR object is remoted outside an application domain, a lifetime lease is created for that object. Each application domain contains a lease manager that is responsible for administering leases in its domain. The lease manager periodically examines all leases for expired lease times. If a lease has expired, the lease manager walks its list of sponsors for that object and queries whether any of them want to renew the lease. If no sponsor renews the lease, the lease manager removes the lease, the object is deleted, and its memory is reclaimed by garbage collection. An object's lifetime, then, can be much longer than its lifetime lease, if renewed more than once by a sponsor or by continually being called by clients.
Because the remote object's life is independent of the lives of its clients, the lease for a simple or lightweight object can be very long, be used by a number of clients, and be periodically renewed by an administrator or a client. This approach uses leases efficiently because very little network traffic is needed for distributed garbage collection. However, remote objects that use scarce resources can have a lease with a short lifetime, which a client frequently renews with a short time span. When all the clients are finished with the remote object, the .NET remoting system deletes the object quickly. This policy substitutes increased network traffic for more efficient use of server resources.
Since it’s a bit complex and needs a sample code, I have not covered this topic. For more information on leases, you can find more at the url(s) below:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconremotableobjects.asp


Channels:
A channel is an object that implements communication between a client and a remote object, across app domain boundaries. The .NET Framework implements two default channel classes, as follows:
· HttpChannel: Implements a channel that uses the HTTP protocol.
· TcpChannel: Implements a channel that uses the TCP protocol (Transmission Control Protocol).
Both of these classes are dual-purpose in that they implement both a client channel, used on the client side to communicate with remote objects, and a server channel, used on the server side to communicate with clients. The HttpChannel class formats messages using the SOAP protocol, which encodes communications as XML. In contrast the TcpChannel class uses a binary format for messages. While binary formatting is more efficient (formatted messages are smaller), the plain text format of SOAP is much less likely to have problems with firewalls and other network security measures.


When and why to choose Marshal by Value or by Reference
Remoting makes an object in one process (the server) available to code in another process (the client). This is called marshalling, and there are two fundamentally different ways to marshal an object:
· Marshal by value: the server creates a copy of the object passes the copy to the client.
· Marshal by reference: the client creates a proxy for the object and then uses the proxy to access the object.
When a client makes a call to an object marshaled by value (MBV), the server creates an exact copy and sends that copy to the client. The client can then use the object's data and executable functionality directly within its own process or application domain without making additional calls to the server. To implement MBV you must either implement the ISerializable interface in your classes, or mark them with the attribute.

In contrast, when a client makes a call to an object marshaled by reference (MBR), the .NET framework creates a proxy in the client's application domain and the client uses that proxy to access the original object on the server. To implement MBR a class must, at minimum, extend the System.MarshalByRefObject class. Figure 1 illustrates the differences between MBV and MBR.

First picture demonstrates MBVSecond picture demonstrates MBR

Given the differences between MBV and MBR, how do you decide which to use when you're programming a remotable class? In some situations you have no choice—you must use MBR, such as when the remote component must run in its own original app domain, in order to access local files or use operating system handles. These operations could not be carried out by a copy of the object running in the client's app domain. You would also need to use MBR when the client must be made aware of changes in the object. When using MBV the copy of the object that is sent to the client is static, and does not reflect subsequent changes to the state of the object on the server.

In many situations, however, either MBV or MBR will work, and the question is which is better? The concern here is that old bugaboo—bandwidth. Ask yourself which technique places fewer demands on the transport between server and client? With MBV you need move the object copy from the server to the client one time. While that can be a significant task with large objects, after the copy is at the client, calls to it are all within the client's app domain and do not involve the transport mechanism at all.

In contrast, MBR does not require a copy of the entire object to be transported to the client—but each and every time the client accesses the remote object it requires either a one-way or round-trip transport of information. Individually these calls may not place a heavy demand on communication, but hundreds or thousands of calls can add up.

Bottom line?
-Small objects that the application accesses frequently are best remoted using MBV.
-Large objects that the application accesses relatively infrequently are good candidates for MBR.

Unfortunately, that leaves a middle ground where the choice between MBR and MBV may not be immediately obvious. You may want to do some performance testing to aid in your decision.






Sample to demonstrate:

This demonstration program presents a simple remoting example. It illustrates the basic tasks involved in creating a remotable class, a server, and a client.

1. Creating Remotable class:

The remotable class (called RemoteClass) contains a single method that returns a "secret" word to the caller. The class constructor displays a console message when a client activates the class. I've included the console message for demonstration purposes only; it's not required for the class to function. the source code for the RemoteClass. Note that the only aspect of the class related to remoting is that it inherits from MarshalByRefObject. You can create the demo code using any text editor and then save it in the project folder under the name RemoteClass.cs. Then, from the command prompt, compile the class using the following command (enter the command on a single line):
csc /t:library /debug /r:System.Runtime.Remoting.dll RemoteClass.cs

The class compiles to the file RemoteClass.dll.

using System;

namespace RemotingDemo {

public class MyRemoteClass : MarshalByRefObject {

public MyRemoteClass()
{
Console.WriteLine("MyRemoteClass activated");
}

public String SecretWord()
{
return "REMOTING";
}
}
}

2. Creating Client:

Next, you must build the client, which will call the remotable class. the client code, called Client.cs. The program does the following things:
1. Creates a TcpChannel on port 8084.
2. Registers the channel with the .NET infrastructure.
3. Attempts to obtain a reference to the remote class by calling the Activator.GetObject() method.
4. If the program can't obtain a reference, it displays a message to the user. Otherwise it calls the remote object's SecretWord() method and displays the returned data.
The call to the Activator.GetObject() method needs some more explanation. The method accepts two arguments. The first is the type of the remote class, which you can obtain by using the typeof() method with the class's namespace and name as argument. The second argument has the following parts:
· tcp://: identifies the protocol being used. Tcp is specified because the client and the server are using a TcpChannel for communication.
· localhost: the name of the computer on which the remote class is located. In this sample, the remote class is on the same computer as the client, so the code uses the name "localhost". If the class were located on a network computer with the name "BIGSERVER", you would use that instead.
· :8085: This identifies the port on which the remote class is listening.
· /Secret: the URI associated with the remote class. This is an arbitrary name and can be anything you like as long as it matches the URI established by the server.
To compile the client, save the code as Client.cs and compile with the following command line (enter the command on a single line). Note that the compiler command specifies a reference to the remotable class RemoteClass.dll that you created previously.
csc /debug /r:remoteclass.dll /r:System.Runtime.Remoting.dll Client.cs

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

namespace RemotingDemo {
public class Client
{
public static int Main(string [] args)
{
TcpChannel chan = new TcpChannel(8084);
ChannelServices.RegisterChannel(chan);
MyRemoteClass obj = (MyRemoteClass)
Activator.GetObject(typeof(RemotingDemo.MyRemoteClass),
"tcp://localhost:8085/Secret");
if (obj == null)
System.Console.WriteLine("Server not found.");
else
Console.WriteLine("The secret word is " +
obj.SecretWord());
return 0;
}
}
}


3. Creating server:

Finally, you need to create the server. The server listens for calls from clients and connects them to the remotable class. Here's what the code does:
1. Creates a new TcpChannel on port 8085. Note that this is the same channel on which the client will look for the remotable class.
2. Registers the channel with the .NET infrastructure.
3. Registers the remotable class using a call to the RemotingConfiguration.RegisterWellKnownServiceType() method. The arguments to this call are:
4. The first argument identifies the class being registered.
5. The second argument specifies the URI for the class. A client will use this URI when looking for the class.
6. The third argument specifies that if there are multiple calls to the class (from more than one client), they will all be services by the same instance of the class.
7. Display a message to the user and then pause until the user presses Enter.
Step 4 is required because the server must be executing to do its job. In other words, only while the server program is running will it "listen" for client requests for the remotable class.

To complete the server, save the code as Server.cs and compile it with the following command line (enter the command on a single line):
csc /debug /r:remoteclass.dll /r:System.Runtime.Remoting.dll Server.cs



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

namespace RemotingDemo {
public class Demo {

public static int Main(string [] args) {

TcpChannel chan = new TcpChannel(8085);
ChannelServices.RegisterChannel(chan);
RemotingConfiguration.RegisterWellKnownServiceType(
Type.GetType("RemotingDemo.MyRemoteClass,RemoteClass"),
"Secret", WellKnownObjectMode.SingleCall);
System.Console.WriteLine("Hit to exit...");
System.Console.ReadLine();
return 0;
}
}
}

Summary

I didn’t have much time to think of a good remoting sample and then discuss that. My main idea of compiling this article was to cover the basic knowledge of .net remoting with a simple test code which I have included.

That’s it for now and after writing such a simple .NET Remoting overview in a simple manner, I hope it will be clear to the reader that how easy is to use .NET remoting and to make your objects remotable.

No comments: