Application Domains and Proxies |
.Net Remoting is the .Net framework's solution for making remote procedure calls. That is, function calls across a process boundary. To facilitate this, the notion of an application domain has been introduced. Application Domains are a logical construction of the CLR. While the classic programming model relyed on the Operating System to provide memory and process space, the CLR must also provide an environment for managed code. The CLR takes a process and creates these Application Domains within which managed code runs. A process can host many of these logical Application Domains each with its own set of loaded assemblies.
|
Image may be NSFW. Clik here to view. ![]() |
While the main application domain is created automatically by the CLR one can be created like this:
|
using System; using System.Reflection; … AppDomain domain = AppDomain.CreateDomain("MyDomain"); … |
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 this a proxy (an instance of the TransparentProxy class) is introduced by the .Net framework at the Client side. On the server a stub is created.
|
When programming with .Net Remoting a remote call to an object in another application domain whether it is in the same process or on a machine across network is transparent to the application. In general three pieces pieces are required.
|
A Server – that provides the remote functionality.
|
A Client – that makes the remote call.
|
A commom interface that is known to both the server and the client.
|
Marshaling |
There are two methods by which a remote object can be made available to a local client object. Marshal By Value (MBV) and Marshal By Reference (MBR). Objects that are marshaled by value are created on the remote server, serialized into a stream and transmitted to the client where an exact copy is reconstructed. This has several implications, first the entire remote object is transmitted on the network. Second, some or all of the remote object may have no relevance outside of its local context. For example the remote object may have a connection to a database or a handle to a window, or a file handle etc, these will in general have no meaning at the client. Third, parts of the remote object may not be serialiazable, for example the database connection mention above. In addition, when the client invokes a method on an MBV object the local machine does the execution, which means that the compiled code (remote class) has to be available to the client. MBV objects are however, very efficient if they are small and provide a repeated function that does not consume bandwidth. MBV classes must either be marked with the [Serilaizable] attribute in order to use the default serialization or must implement the ISerializable interface and override the standard serialization method: void GetObjectData( SerializationInfo info, StreamingContext context); to provide its own serialization.
|
Marshal By Reference passes a reference to the remote object back to the client. But unlike a C++ reference (or pointer) it does not refer to a memory location but is rather an ObjRef class, that contains all the information required to generate the proxy object that does the communication with the actual remote object. On the network only parameters and return values are passed. A remote method invocation requires the remote object to call its method on the remote host (server). MBR classes must inherit from System.MarshalByRefObject. An ObjRef is a serializable representation of an object that extends MarshalByRefObject.
|
Channels, Messages and Sinks |
The .Net Remoting infrastructure provides the mechanism by which a stream of bytes is sent from one point to the other (client to server etc.). This is acheived via a channel. Strictly speaking it is a class that implements the IChannel interface. Channels send each message along a chain of channel sink objects prior to sending or after receiving a message. Two pre-defined .Net Remoting channels exist in System.Runtime.Remoting.Channels, the TcpChannel and the HttpChannel. To use the TcpChannel, ther server must instantiate and register the TcpServerChannel class and the client the TcpClientChannel class.
|
A message is a class that at the very least implements the IMessage interface. A message-sink implements the interface IMessageSink, they receive notifications about messages and also process the messages. Message sinks are chained together, one sink will process a message and pass it on to the next sink in the sink chain.
|
Here is a complete example of the client and server:
|
// The Server using System; using System.Runtime.Remoting; using System.Runtime.Remoting.Channels; using System.Runtime.Remoting.Channels.Tcp; namespace RemoteServer { public interface IRemoteCom { string DoWork(string message); } public class RemoteServerObject : System.MarshalByRefObject,IRemoteCom public string DoWork(string message) class RemoteServer public RemoteServer() [STAThread] System.Console.WriteLine("Remote Server Ready on Port:{0}…", rs.mPort); r public interface IRemoteCom class RemoteClient </enter> |
This is the smallest example I could think of, notice that the common interface lives in the server namespace. Which means that the client must include the server's namespace. This in general is not feasable. It also places a very severe restriction on this trivial example in that both the server and the client must run the same machine. Without the common interface one machine's environment cannot know about the other. Typically a third namespace is created that contains the common interface, and resides in its own assembly (.dll file). Still, there is a contrived way around this, declare the interface in both the server and the client, but only implement the interface's methods on the server (I admit, its very contrived). Also note in RemotingConfiguration.RegisterWellKnownServiceType(…) the parameter WellKnownObjectMode.SingleCall is used, this means that a remote object is created for every remote call the client makes. We examine this in part 2.
|
↧
.Net Remoting – Part1 Introduction
↧