Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Dot Remoting - Server Activated, SingleCall Technique

0.00/5 (No votes)
11 Jan 2011 1  
Shows how you can create remote objects and access it from client. Here, it is server activated single call technique

1. Introduction

.NET remoting is client and server based distributed object technology. In this first article about .NET remoting, we will create a remote server and client application. We will go ahead and start creating the application and I will give the explanation when we are developing the example.

2. About this Example

The server we are going to create is a console application. This console application will host our remote objects on the server and the client will make a call to the public members (usually function).

The client is a Windows Form application, which will get access to the remotely hosted objects and start using it. Below is the screen shot of the client application.

Pic_00.JPG

When we click the Get Details button, the client makes a call to the remote server console application to get the customer id and customer name from the remote objects. Last deposit and Last withdraw is populated by getting the LastTrans object from the remote object. I will explain other concepts when we move along.

First, we will go ahead and start our Remote server console application.

3. Remote Server Console App

  1. Create a new console application and name it ConServer.
  2. Right click the ConServer project and choose Add reference.
  3. From the dialog displayed, select System.Runtime.Remoting from the .NET tab and click the OK button. This step provides access to the .NET remoting API.
  4. Next add a class named LastTrans to the project. Add one more class and name it as RemCustomer.

Explanation

We have created a console application project and then got access to the .NET remoting assemblies. Then we added to classes to the project. RemoteObject is the one which will be kept in the Server’s memory. And LastTrans object is created in the server but it will be sent to client through serialization using the RemoteObject.

Serialization is a technique, which converts your class in the form of bit streams and these steams in the receiving end is collected to form the object. In our example, we sent the LastTrans through serialization to the client.

All the skeleton of our server is kept ready by the IDE. Now we will go ahead and add code.

4. The LastTrans Class

  1. Locate the LastTrans class created by the IDE and mark it as Serializable by adding the serializable attribute before the class. Below is the code for it:
    //RemoteServer_018: Make the Class Serializable
    [Serializable()] 
    public class LastTrans
  2. Add private variable to this class:
    //RemoteServer_011: Private field for the Newly added class
    private int LastDeposit;
    private int LastWithdraw;
  3. In the constructor, initialize the above declared private variables. Note that here I hard-coded the values. In the real world, it will be queried from the database to get the latest result. Below is the code:
    //RemoteServer_012: Constructor for Last Transactions. At present we will
    //Default it to some constant value
    public LastTrans()
    {
        //Hard Coded here. In real world make a query to the Database to get 
        //the latest information.
        LastDeposit = 68800;
        LastWithdraw = 12000;
    } 
  4. Next, provide a function to return the private variables. The client to get the Last Deposit as well as Last Withdrawal amount uses these functions.
    //RemoteServer_013: Get the Last Transaction amount
    public int GetLastDeposit()
    {
        Console.WriteLine("Last deposit Queried...");
        return LastDeposit;
    }
    
    public int GetLastWithdraw()
    {
        Console.WriteLine("Last Withdrawal amount Queried...");
        return LastWithdraw;
    }

Note that the console write line does not print anything on our Remote Server because, the object is serialized and sent to client. The client creates this object and subsequent call on the object gets executed in the client machine.

5. The RemCustomer Class

  1. Include the below specified namespace:
    //Remote_003: Include the Namespace
    using System.Runtime;
  2. This class acts as the remote object. To make the IDE created object (Refer to step 4), locate the class and derive it from the MarshalByrefObject. OK. Why is that derivation required. It is required as we are planning to keep this object server’s remote pool. Below is the second step of the code:
    //RemoteServer_004: Make the class Remotable by inheritance.
    public class RemCustomer : System.MarshalByRefObject
  3. Next, declare the members for this class. Note that our remote object is going to serve the client both standard data type as well as user defined type. User defined type here is LastTrans which you already saw that we marked it as serializable.
    //RemoteServer_005: Fields on the remote Class
    private string CustName;
    private int CustId;
    //RemoteServer_014: Instance for LastTrans declared
    private LastTrans trans;
  4. The constructor will initialize the members declared. Constructor is below:
    //RemoteServer_006: Constructor for the Remote Object
    public RemCustomer()
    {
        CustName = "Ram Gopal";
        CustId = 1235;
        Console.WriteLine("Instance of Remote object Created...");
    
        //RemoteServer_015: Instance for LastTrans created
        trans = new LastTrans();
        Console.WriteLine("Instance of Last Transaction object created. ");
    }
  5. Other member functions are shown below. These can be easily understandable.
    //RemoteServer_007: Get the Customer id
    public int Get_id()
    {
        Console.WriteLine("Customer Id requested...");
        return CustId;
    }
    
    //RemoteServer_008: Get the Customer Name
    public string Get_Name()
    {
        Console.WriteLine("Customer Name requested...");
        return CustName;
    }
    
    //RemoteServer_017: Instance for LastTrans declared
    public LastTrans GetLastTrans()
    {
        Console.WriteLine("Transaction object requested...");
        return trans;
    }

Now our remote class is also ready to serve the Windows Form client. Note that the MarshalByrefObject states that this RemCustomer will reside on the server and a reference to it is sent to the client. The client calls that reference as proxy. We will move to our last step which is the program entry point of console application.

6. Hosting the Remote Object on the Server

  1. Locate the static void main, which is the program entry point for the console application. In the top of the file (Program.cs if you had not changed the file name), include the assemblies. Below is the code:
    //RemoteServer_001: Required Assemblies
    using System.Runtime;
    using System.Runtime.Remoting;
    using System.Runtime.Remoting.Channels;
    using System.Runtime.Remoting.Channels.Tcp;
  2. Next a TCP channel with port number 13340 is created and registered in the server machine. Client will use this port to communicate with remote object. The below code creates a TCP communication channel and registers it with the server machine in which the server application is going to run.
    //RemoteServer_002: Create a communication channel (Server) and register it
    TcpServerChannel SrvrChnl = new TcpServerChannel(13340);
    ChannelServices.RegisterChannel(SrvrChnl, false);
  3. Once the communication method is specified, it is time to register our remote object in the server machine. The first parameter to the function specifies the type of the object that is registered. The second one gives a unique name for the registered object. I have kept the registration name the same as the class name. But, you can use a different name. Client should use the same name when they ask for the Proxy of the remote object. The third parameter says how the serve should activate the remote object. In this example, we are using the Single Call method. That means, for each client call, an object will be created and maintained in the pool.

    We will look at a singleton method in the next article:

    //RemoteServer_009: Register the Remote Class so that the Object can go 
    //and sit on the Remote pool
    RemotingConfiguration.RegisterWellKnownServiceType
    	(typeof(ConServer.RemCustomer), "RemCustomer", 
    	WellKnownObjectMode.SingleCall);
  4. The server is ready. Break the execution using the ReadKey method.
    //RemoteServer_010: Halt the server so that Remote client can access the object
    Console.WriteLine("Server is Running...");
    Console.WriteLine("Press Any key to halt the Server");
    Console.ReadKey();

If you want, you can run the server now. But, there is nobody to consume the registered remote object on you server. We will now move to creating the Client. Below is a screen shot:

Pic_01.JPG

Note: The remote object is not created as the activation method SingleCall. For each client, call a separate instance of the remCustomer will be created and kept in the remote object pool.

7. Prepare the Client Application

As you already know, client is a Windows Form application. Follow the steps below to create the client application that uses the remote object hosted by our console server.

  1. Make sure the Console server project is still in open state.
  2. Click on File|Add|New Project.
  3. Select Visual C# in the project Types and Select Windows Application from the available template.
  4. Name the project as RemClient and click ok.
  5. Design your form by referring the first screen shot. Download the attached project for your reference and set the properties by referring it. ConServer.sln will open both the projects. In your case, this solution will be created now as you are adding one more project. A solution file is the combination of two or more projects.
  6. Add a reference for Remoting assembly as you did in the server step 3.
  7. Once your form is designed, double click the Button control to get the Click event handler for it.
  8. Right click the RemClient project and select add reference. Go to the project tab and select ConServer project.

Explanation

In the above steps, you created a Windows application and designed the form. You added reference to the .NET's Remoting assembly and added a reference to the ConServer application. If we use the interfaces, we can avoid this project reference. We will see that in a separate article.

8. Start Coding the Client

  1. First include the below specified namespaces on top of the file which has the click event handler for the button. The code is below:
    //RemoteClient_001: Include the required namespace
    using System.Runtime.Remoting;
    using System.Runtime.Remoting.Channels;
    using System.Runtime.Remoting.Channels.Tcp;
    using ConServer;
  2. Now we will implement the click event handler. The button click will invoke the public functions exposed by the Remote object. Make sure the RemCustomer on your server application is Public. The first step is to get the Proxy for the remote object hosted by the Console Application, which runs on Local or Remote machine. Below is the code for doing that:
    //RemoteClient_002: Get the remote object on the server
    RemCustomer remoteCust = (RemCustomer)Activator.GetObject(typeof(RemCustomer), 
    			"tcp://localhost:13340/RemCustomer");

    In the first parameter, we specified what object we are looking for. In our case, it is the actual object type. The project reference we added is just to resolve this type (RemCustomer) name. But, in the interface approach, it is not required to reference the server project. Just an interface type is required on both server and client. If the client develops the application to invoke the third party remote object, then the server developers usually provide the interface. By doing that server piece of implementation is not revealed to the client developers. In our case, let us assume that the same party develops server and the client.

    The second string parameter has three parts in it. The first one is machine name. As tested the applications (Server, Client) on the same machine I kept localhost. If the Server application is running on the machine names C-AshCorner_01 then the localhost in the string should be replaced by the machine name; that is; C-AshCorner_01. Note you can also use the IP address of that machine.

    Well. The client now knows which machine it need make connection to get the RemCustomer proxy. But the server may have a lot of network communication right? It may be an Oracle server or Sql2005 server or even a Jboss web server. How does the server make communication? That is why we registered the server with a port number 13340. This port on TCP communication is called dedicated port. Oracle has its dedicated port. Jboss has it own dedicated port. Our application server registered the port 13340 saying “This port is in use like 80 for http”. Our client application by specifying this port number next to the machine name, sets-up the communication for connection request. The last part specifies the registered name of remote object. Look at the Section 6 point 3.

    Finally, we performed a type cast and stored the proxy in the remoteCust.
    In summary, to get the remote object:

    1. First a machine name is resolved
    2. A port number specifying which particular Server Application contacted.
    3. The registered name specifies a single object type upon several registered remote objects (We registered only one)
  3. Once the proxy is with us, make a call to the functions through proxy. Note proxy just shows that the object is with you, but it is not. All the calls are transmitted to the server to get the result. Below is the code, which makes use of the proxy object to make a call on the public functions, exposed by the remote object remCutomer.
//RemoteClient_003: Get Customer Id and Name exposed by the remote object itself
int id = remoteCust.Get_id();
string name = remoteCust.Get_Name();

//RemoteClient_004: Get Some other object from the server through the remote
//object. Note the object should be serializable.
LastTrans trans = remoteCust.GetLastTrans();
int lastdeposit = trans.GetLastDeposit();
int lastwithdraw = trans.GetLastWithdraw();

//RemoteClient_005: Display the information retrieved
txtCustId.Text  = id.ToString();
txtCustName.Text  = name;
txtLastDeposit.Text = lastdeposit.ToString();
txtLastWithdraw.Text = lastwithdraw.ToString();
btnInvokeRemote.Enabled = false;

The picture below explains how the application will work:

Pic_02.JPG

9. Testing the Application

On the Same Machine

  1. Right click the solution and Click rebuild all.
  2. Now navigate to both the EXEs using Windows Explorer.
  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, say 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 at your machine.
  5. Click the Get Details button.

Note: You can use IP address also in-place of Machine Name.

Pic_03.JPG

10. Closing Note

  1. To see the result live, download the screen cam: Download
  2. To know how to debug, download to see the steps: Download

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here