.NET Channels And Remoting Architecture

Introduction

In Common Language Runtime (CLR) environment, instead of a process, the basic unit of isolating applications in the running environment is an application domain. The application domain is the smallest unit of execution and several application domains can run within a single windows process. Here, each application domain will have its own code, configuration settings, and data. An application domain cannot directly gain access to the code, data, or configuration settings of other application domains. If the code running in one application domain fails or is stopped by the CLR, it will not affect the execution of code in another application domain. Typically, it is the runtime that creates and manages application domains for your applications. Today’s applications however cannot always run in an isolated, independent mode and often need to interact with each other across boundaries. This is especially so in the case of distributed systems which are very much in need today.

.NET remoting is a mechanism using which developers can create distributed systems. In remoting, remote objects are exposed to a process, thus allowing inter-process communication. The applications involved in the remaining architecture can be located on the same computer, different computers on the same network, or computers across remote networks. Remoting provides a framework wherein developers can easily create applications that can communicate with each other across several application domains.

There are actually two technologies that support distributed application development, namely,

  • XML Web Services
  • Remoting

XML Web Services provide the means to interact with objects over the internet. Remoting is a preferred approach when both the endpoints (client and server) are in your control.

Implementing Remoting

Remoting represents an object which executes outside the application domain. The two processes can exist on the same computer or on two computers connected by a LAN or the Internet. When an object needs to be passed across a network or application boundary, its in-memory representation needs to be converted to an out-of-memory form. This is called marshaling, and there are two basic ways to marshal an object:

  • Marshal by value
    The Server creates a copy of the object and 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.

Creating an Application Domain

Application Domains are created automatically by Common Language Runtime. However, application domains can also be created and can be loaded into assemblies.

The following code creates an application domain called “Ashish” and then displays the name of the host domain and the newly created domain.

private void TestForm_Load(object sender, EventArgs e) {
    AppDomain domain = AppDomain.CreateDomain(“ashish”);
    MessageBox.Show(“Host Domain: ”+AppDomain.CurrentDomain.FriendlyName + “” +”Child domain: ”+domain.FriendlyName);
}

The architecture of .NET Remoting

The fundamental concept of remoting is that object references are used to communicate between servers and clients. A new instance of the remote object is created and the client then receives a reference of the server object. The methods can then be called using the objects created.

The remoting system uses proxy objects to provide an impression that the remote object is in the client’s process. A proxy is like a stand-in, a copy of the original remote type. In simple terms, a proxy is a local object, which is an image of the remote object.

.NET Channels And Remoting Architecture
Figure 1 :Remoting Architecture

The architecture shows the client calling the remote object through the transparent proxy. A client that makes use of an object across any kind of remote boundary is actually making use of a transparent proxy for the object. The transparent proxy provides the illusion such that the actual object is residing on the clients system. The transparent proxy achieves this by forwarding the calls made on it to the real object using the remoting infrastructure.

The transparent proxy is itself accommodated by an instance of another class which is of the type RealProxy. This object is used in implementing a part of the functionality required to forward the operations from the transparent proxy.

The client is not aware of the existence of the transparent proxy, as far as it is concerned , it assumes that it is communicating with the object. The transparent proxy calls the real proxy. The real proxy is “pluggable” meaning it can be replaced by any of the replacements for other networking channels available with the .NET framework or a developer’s own implementations, By default, the real proxy locates the sinks and passes the message there. The sink, in turn receives the message into the channels. The channel serialize the message depending on the formatter associated with the channel and then sends the message across the network.

.NET Channels And Remoting Architecture
Figure : Message de-serialized at the server side

The channel on the server-side picks up the formatted message from the network. The channel deserializes the message with the help of the associated formatter. The message is then sent to the server sink. From the server sink the message is forwarded to the appropriate object sink. The object sink, in turn, then calls the method of the remote object.

Channels

A channel is an object that enables communication between a client and a remote object across application domains. Channels are implemented using transport protocols for passing messages between remote objects. A channel takes a stream of data and creates a package for a transport protocol and sends it to the destination machine.

.NET Channels And Remoting Architecture
Figure : Channel Architecture

.NET Framework supports two types of channel classes , namely TCP and HTTP channel classes. The TCP Channel classes use TCP protocol at both ends whereas the HTTP channel classes use HTTP protocol at both ends, It is also possible to create custom channels through the process is quite complex.

Table below shows the HTTP channel classes.

Class Name Description
HttpServerChannel Defines an implementation of a server channel that uses HTTP to communicate.
HttpClientChannel Defines an implementation of a client channel that uses HTTP to communicate
HttpChannel Defines an implementation of a combined client and server channel that uses HTTP to communicate.

Table below shows the TCP channel classes.

ClassName Description
TcpServerChannel Defines an implementation of a server channel that uses TCP to communicate.
TcpClientChannel Defines an implementation of a client channel that uses TCP to communicate.
TcpChannel Defines an implementation of a combined client and server channel that uses TCP to communicate.

Building a Simple Remoting Server

Consider a scenario where a company named ABSystems wants to calculate the bonus for each of its employees through an application. However, instead of storing the front-end client application and the logic for computing bonus on the same location, the company wants to store the computing logic at a remote location. This can be accomplished by using. Net remoting . First , a remotable class is created to implement the bonus logic .

Using System;
namespace ABSystems {
    public class empbonus: MarshalByRefObject {
        public float CalcBonus(int salary) {
            float bonus = (10.0 F / 100.0 F) * salary;
            Console.WriteLine(bonus);
            return bonus;
        }
    }

The class empbonus is derived from MarshalByRefObject to make it remotable. This file will be compiled into an assembly that contains the metadata needed by both, the client project, and the server project, to communicate with each other. It contains the simple logic to calculate bonus for an employee based on his salary . This remote method will now be invoked by a remote client, But first , a remoting server needs to be implemented.

Next, a simple remoting server needs to be created . A remoting server is nothing but an object that creates and registers a server channel to listen on. Example below shows the code for this,

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Http;
using ABSystems;
namespace EmpRemotingSample {
    public partial class EmpServer: Form {
        private void EmpServer_Load(object sender, EvnetArgs e) {
            HttpServerChannel objHttpChannel;
            objHttpChannel = new HttpServerChannel(1234);
            ChannelServices.RegisterChannel(objHttpChannel);
            RemotingConfiguration.RegisterWellKnownServiceType(typeof(EmpBonus), “EmpBonus”, WellKnowObjectMode.SingleCall);
            System.Console.WriteLine(“Hit Enter Key to Exit…”);
            System.Console.ReadLine();
        }
    }

An instance of the HTTPServerChannel class is created. The channel is created on port number 1234. RegisterChannel() method is used to register the channel object. The remote type created in previous example, empbonus is registered with the channel services. The RegisterWellKnownServiceType() method of the RemoteConfiguration class is used to achieve this and registers the class as a well known type. The method takes in three parameters. The first parameter is the type of the class which is to be registered , In this case , the class created in previous example named Empbonus . The second parameter is a name for referring the service and the third parameter is the object model which is an enumeration member that could be either SingleCall or a Singleton.

The Server waits for the user to press the Enter key before exiting.

Building a Simple Client

The following code creates a simple client for the server created in previous example

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Http;
using ABSystems;
namespace ABClient {
    public partial class Client: Form {
        private void btnSubmit_Click(object sender, EventArgs e) {
            HttpClientChannel objchannel;
            objchannel = new HttpClientChannel();
            ChannelServices.RegisterChannel(objchannel, true);
            EmpBonus obj = (EmpBonus) Activator.GetObject(typeof(EmpBonus), ”http: //10.2.1.78:1234/EmpBonus”);
                if (obj == null) {
                    MessageBox.Show(“Could not Locate Server”);
                } else {
                    float bonus = obj.CalcBonus(Convert.Toint32(txtSal.Text));
                    MessageBox.Show(bonus.ToString());
                }
            }
        }
    }

In this example, the RegisterChannel() method is called to register the channel. An object of the class HttpClientChannel is passed to the RegisterChannel() method to register a new HTTP channel. An object of EmpBonus class from previous example is created . The static GetObject() method of the Activator class is then used which contains methods to create types of objects locally or remotely. The GetObject() method takes in two parameters, the first being the type of the class that contains the code for the remote object and the second parameter being the URI of the remote object with the port number.

The client and server created in the above code make use of the HTTP channel.

Consider a scenario where you want to host your remote object on a different machine . In such a case, it is recommended that you use IIS to host the object so that it can be invoked remotely on the client machine.

The code below in examples demonstrate how to achieve this, first , a remotable class named RemoteGraphix is created

using System;
public class RemoteGraphix: MarshalByRefObject {
    public DateTime GetServerTime() {
        return DateTime.Now;
    }
}

The code in this class only retrieves and returns the current date and time. When this class is built , a dll RemoteGrafix.dll is generated . Assume that you want to host on a machine named “developer”. Under the folder c:\Inetpub\wwwroot of that machine , you need to create a folder “RemoteGrafix\bin” and copy the dll to the bin folder. Thus c:\Inetpub\wwwroot\RemoteGrafix\bin will have the remote class library RemoteGrafix.dll. Now, you need to create a wen.config to indicate the remoting details.

<configuration>
    <System.runtime.remoting>
        <aaplication>
            <service>
                <wellknown mode=”singlecall” type=”RemoteGrafix, RemoteGrafix” 
                objectUri=”RemoteGrafix.rem” />
            </service>
        </application>
    </system.runtime.remoting>
</configuration>

In this config file, you specify details similar to what you specify in your sever/client classes. The advantage of using a configuration file to take care of these details is that whenever any specification changes, all you need to do is change the .config file instead of editing the .cs file and re-compiling every time. The .config file specifies that the mode will be SingleCall, the type of the remotable type is RemoteGrafix, and the name of the assembly is RemoteGrafix. As the dll will be hosted on IIS , the uri is given as RemoteGraffix.rem. You will then copy this web.config file to the c:\Inetpub\wwwroot\RemoteGrafix folder of the remote machine. Then, launch IIS on the remote machine and create a virtual directory with the alias RemoteGrafix. The virtual directory should point to c:\Inetpub\wwwroot\RemoteGrafix folder.

Next, the client class is created on the current machine (not remote machine). It is possible to skip the creation of server and test the remote object directly through the client . The code is below example assumes that a form named ClientForm is created.

public void ClientForm_Load(object sender, EventArgs e) {
        HttpClientChannel objchannel;
        Objchannel = new HttpClientChannel();
        ChannelServices.RegisterChannel(objchannel, true);
        RemoteGrafix obj = (RemoteGrafix) Activator.GetObject(typeof(RemoteGrafix), “http: // developer/RemoteGrafix/RemoteGrafix.rem”);
            If(obj == null) {
                MessageBox.Show(“Could not Locate Server”);
            } else {
                MessageBox.Show(“Result from the remote object” + obj.GetServerTime().ToString(), ”Information”, MessageBoxButtons, OK, MessageBoxIcon.Information);
            }
        }

This code creates and registers an HttpClientChannel instance. Observe that the port number is not specified anywhere in this example. This is because IIS uses port 80 by default. The code retrieves an instance of RemoteGrafix using the GetObject() method of Activator class. In this case, the URI includes the machine name of the remote machine named “developer”. The GerServerTime() method is then involved in the MessageBox.Show() method directly.

Thus the remote method present in a class on another machine can be invoked using remoting and IIS.

Summary

.NET remoting is a mechanism using which developers can create distributed systems. An application domain is the smallest unit of execution and several application domains can run within a single windows process. Application domains are created and managed by CLR, although it is also possible for a developer to create a custom application domain. Remoting offers features such as flexibility, scalability, and so forth. TCP and HTTP channels are commonly used for creating communication channels in a remoting system and .NET provides relevant classes to create and work with these channels.