Sunday, June 26, 2011

[ Dot Net Remoting ] - Client activated remoting objects


1. Introduction


In the previous article, I had written about "Server Activated" remote objects. Also provided a separate article for Single Call and Singleton on the Server activated remote objects. In this post, we will explore how do we use the "Client activated" remote objects.

Before we go on Client Activated remote objects a short note about what is Activation and where the object lives. The obvious thing is whether it is server activated or client activated, the remote object lives in the "remote pool" of the server.  Client activation means, the client creates the object on the server’s remote pool using the operator new. So, if you are developing a class for the Client Activated Remote object, you have the liberty of using the overloaded constructors.

In Server activated – Single call technique, the remote object is created during the call and destroyed when the call is over.
In Server activated – Singleton technique, a single object is maintained for client requests between the call. All clients share the object state
In Client Activated technique, the client creates the object on the remote pool the object is dedicated to the client who created it. So here the object state is different for objects created by client/clients.

Now let us go ahead start creating an example for the Client Activated remote object.

2. About the Sample


Below is the screen shot:

Fig 1: Sample Application


The console window is the server exe that waits for the client’s activation request to host the dedicated object in the remote pool. The client is a windows application, which demonstrates the use of the client activation.

Set First Ac button creates a remote object on the remote pool and Display Ac1 retrieves the Object’s state information from the remote machine. Similarly, the other button pair second account does the same. This will give an idea that each object created by the client maintains its own state as Display Ac1 and Display Ac2 button clicks are going to retrieve different information.

3. Remote Server – Account Class


The remote server is created as the C# console application project. The project is named as ServerCA (spell mistake! What to do?). After creating the project dot reference for system.runtime.remoting is added to the project.

1) First, the required namespace provided in the top. Below is the code:

//001 ServerCA : Name space for Client Activated Server
using System.Runtime.Remoting;

2) Then the Account class is created. And, this class is derived from the MarshalByRefObject to support the remoting of the object created from it. Then some variables related to accounts are declared. These variable (in objects world, the object states) are useful to check the each cleint activated objects mantains their states.

//002 ServerCA : Remote Object, that will be Activated by Client
public class Account : MarshalByRefObject
{
 private int AcNumber;
 private string AcHolderName;
 private int AcBalance;

3) The constructor shown below initializes the data members of the Account class. I hope no more explanation is required here.

//003 ServerCA : Initilize the Ac with zero, noname
public Account()
{
 AcNumber = 0;
 AcHolderName = "";
 AcBalance = 0;
 Console.WriteLine("Account Object Created - Default Ctor");
}

4) One more constructor is provided for the Account class that helps to initialize the data members when the object is created. Notice that the Server Activated remote class does not support these kind of overloaded constructors. Refer my previous articles to know about the server activated remote objects. As the object of this class is going to be activated by the client (using the new operator) it is now possible to have the overloaded constructors. That means your class can have constructors that accepts parameters to it. Below is the code for it:

//004 ServerCA : Accout with Data. Note Constructor is Overloaded as the activation
// type we are going to set is Client
public Account(int AcNo, string Name, int Bal)
{
    AcNumber = AcNo;
    AcHolderName = Name;
    AcBalance = Bal;
    Console.WriteLine("Account Object Created - Overloaded Ctor");
}

5) OK. Now the account class has data members and constructors to initialize the data memebers. When the default contructor that is a constructor without any parameters is invoked there should be a way to initialize the members. So we will provide a get and set methods for the members. Below is the code:

//005 ServerCA : Set methods for the Private data members
public void SetAcNumber(int AcNo)
{
    AcNumber = AcNo;
}
public void SetAcName(string Name)
{
    AcHolderName = Name;
}
public void SetBalance(int Bal)
{
    AcBalance = Bal;
}

//006 ServerCA : Get methods for the Private data members
public int GetAcNumber()
{
    Console.WriteLine("Account Number Requested");
    return AcNumber;
}

public string GetAcName()
{
    Console.WriteLine("Account Name Requested");
    return AcHolderName;
}

4. Remote Server – Program Main


1) In the program.cs file, required namespaces are first included

//007 ServerCA: Required Namespaces
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Http;

2) Register the required communication channel. Here the sample code took the Http communication channel and registers the port 10038 for communication.

//008 ServerCS : Setup the Http Channel and Register it
HttpChannel port = new HttpChannel(10038);
ChannelServices.RegisterChannel(port, false);

3) RegisterActivatedServiceType function call tells the server that the Account class can be activated from the client.  Now our account class will kept in the remote pool when the client creates the object of it using the new keyword. Application name is used by the client to make a service request of the server object. Below code registeres the Account object as a client activated remote object:

//009 ServerCS : Set the App Name and Register the object type that
// need to be activated by the client.
RemotingConfiguration.ApplicationName = "ServerCA";
RemotingConfiguration.RegisterActivatedServiceType(typeof(SercerCA.Account));

4) Finally, the server waits for the key stroke after printing the information message on the console window to terminate itself.

//010 ServerCS : Inform Server is ready
Console.WriteLine("Server is ready to Demo Client Activated Objects...");
Console.ReadLine();

The server is ready now. First we created the Account class, which a remote class as it is derived from the MarshalByRefObject. We provided some data members to it and get and set function to those members. Also we provided two constructors to it as it is going to be a client activated remote object. Then in the main program entry we registered an http communication channel claiming a port 10038 for dedicated use. Right! Let us move to the client and see how it activates the Account object from this running server.

5. Client Project


The client is a windows application. I named the project ClientCA. To know the form setup, download the code and check the properties for each control that appears in bold. What the client will do is already explained in section 2 of this article.

1) As a first step, the project is created on the same server project using File->Add->New project. Then the dot net runtime for remoting is provided through the reference. The reference to System.Runtime.remoting is done through the .Net tab of the reference dialog. Also for this windows project, add sever project is added as the reference using the same Add reference dialog’s projects tab.

2) In the form main class, the following name spaces are included.

//ClientCA 001: Set the Required Namespaces.
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Http;
using System.Runtime.Remoting.Activation;
using SercerCA;

3) Two instances of Account class are declared in the Form class. Note that we already provided the Server project as a reference. When the solution (Created for you when you added the second project) is built, it will give two exes. One for Client (Windows App) and another one is for Server (Console App). You may deploy the application in server and client machines to test it.

//ClientCA 002 : Declare the Objects that need to be created on server
//and activation are done by the client
Account account1, account2;

4) In the constructor for the form provided by the IDE, the client application registers the Account class of the Remote server. Note that the server already registered the Account class as the Client Activated by using the utility function RegisterActivatedService type in Section 4 point 3. The below specified client code claims the server that it can activate the Account class any time using the utility function RegisterActivatedClientType. Once both and client are agreed upon the activation of the Account, the client can instantiate the Account object just like how it creates the other normal class objects.

//ClientCA 003 : Register the Client Activated type from the remote Pool.
//Note, Server already registered Account as the Activated Type.
RemotingConfiguration.RegisterActivatedClientType(typeof(Account),
    "http://localhost:10038/ServerCA");

6) Set First Ac Button Click – Client


The first account is created using the default constructor and then setting the variables through the set functions. Note the Account object in the server is activated and kept in the remote pool when the client creates the object using the new keyword. So now there is an Account object in the server remote pool, which is activated by the client. Read my Previous articles to know how the client requests Server Activated remote object.

private void btnAc1Set_Click(object sender, EventArgs e)
{
    //ClientCA 004 : Create the Account Object1
    account1 = new Account();
    account1.SetAcNumber( Int32.Parse(txtAcNo.Text));
    account1.SetAcName(txtAcName.Text);
    account1.SetBalance(Int32.Parse(txtBalance.Text));

    //Clear the Fields and Say Account created
    txtAcName.Text = "";
    txtAcNo.Text = "";
    txtBalance.Text = "";
    MessageBox.Show("Account Created");
}


7) Set Second Ac Button Click – Client


The second account is created using the overloaded constructor. And this object also sits in the remote pool of the server. So now, there are two objects in the server and their life are activated by the client. Also, note that these two objects maintain their object state independently. That is, for Example, Account1 may have a balance of 1000 and Account2 may have a different balance of 1200. To see that, next two button click events are handled.

private void btnAc2Set_Click(object sender, EventArgs e)
{
    //ClientCA 005 : Create the Account object2 using overloaded Constructor
    int AcNo = Int32.Parse(txtAcNo.Text);
    int Bal = Int32.Parse(txtBalance.Text );
    account2 = new Account(AcNo, txtAcName.Text, Bal);

    //Clear the Fields and Say Account created
    txtAcName.Text = "";
    txtAcNo.Text = "";
    txtBalance.Text = "";
    MessageBox.Show("Account Created");
}

8) Retrieving the State information of the two Accounts


The next two button events make use the accounts created previously to get the account details. The code is given below:

private void btnAc1Get_Click(object sender, EventArgs e)
{
    //ClientCA 006 : Get the Details of First Object.
    txtAcName.Text = account1.GetAcName();
    txtAcNo.Text = account1.GetAcNumber().ToString();
    txtBalance.Text = account1.GetBalance().ToString();
}

private void btnAc2Get_Click(object sender, EventArgs e)
{
    //ClientCA 007 : Get the Details of First Object.
    txtAcName.Text = account2.GetAcName();
    txtAcNo.Text = account2.GetAcNumber().ToString();
    txtBalance.Text = account2.GetBalance().ToString();
}

9) Testing the App


On the Same Machine



1) Right click the solution and Click rebuild all.
2) Now navigate to both the exe using windows explore.
3) Run the Console Server
4) Run the Windows application
5) Click the button on the Windows application and Observe the result on the Client. 

On Different Machines


1) Copy Server to a Machine says Mahesh. Here, Mahesh is the name of the machine.
2) Have the client on your machine itself. Before that Search for the keyword Localhost and change it to Mahesh.
3) Run the server at machine Mahesh.
4) Run the client on your machine
5) Click the Get Details button.

You may have a Question that when will these client activated object removed from the remote pool. How does the GC work?. Well, Collecting the information for Remote Object Life time. See you in the next article.

Note: The samples are created using the VS2005 IDE

Source Code and Running App Demo: Download

Extracted Zip gives you Source Code and Video of Testing the App. To see the video, set the resolution to 800x600 and use full-screen option from the video.

No comments:

Post a Comment

Leave your comment(s) here.

Like this site? Tell it to your Firend :)