Click here to Skip to main content
15,860,844 members
Articles / Programming Languages / C#
Article

About .NET Remoting: Three concepts Compared and Simplified

Rate me:
Please Sign up or sign in to vote.
3.84/5 (15 votes)
5 Apr 20056 min read 96.9K   1.2K   42   20
An article on .NET remoting which discusses and compares the three ways, by which .NET remoting can be used to access a Server-side object from the clients- Singleton, SingleCall and Client Activation.

Sample Image - AboutRemoting.gif

Introduction

In .NET Remoting, Singleton, SingleCall and Client Activation are the three different ways, which can be used to access a Server-side object on the client through MBR (MarshalByReference). This article uses a sample application which compares and simplifies these three concepts.

I have tried to limit the size of this article and focused on the main topic. Following are the introductions of these three concepts:

  1. Singleton: Same instance of a Server-side object is used by all the clients for all the requests.
  2. SingleCall: Whenever a new call is received, a new instance of the Server-side object is created and reference is passed to the client. Therefore, for each call to the server, the client gets a new instance of the object.
  3. Client Activation: In this, the Client requests to the server for creating a new instance which can be used for multiple calls. The instance activated by a client is not used by other clients. Client-Activated objects can store state information between method calls for its specific client.

Please note that you must derive that class from MarshalByRefObject, which is to be exposed to the clients to get the reference.

Singleton

As mentioned earlier, one Singleton object on the server is used by all the clients.

On the Server:

Mention the following settings in the "App.config" file.

ASP.NET
<configuration>
   <system.runtime.remoting>
      <application name="MyRemoting">
         <service>
            <wellknown mode="Singleton" type="MyRemoteService.MyService, 
           MyRemoteService" objectUri="MyService.rem"/>
         </service>
         <channels>
            <channel ref="http" port="9999" />
         </channels>
      </application>
   </system.runtime.remoting>
</configuration>

In the above code, type contains the type of the object to be exposed on the server. objectUri is any specific name assigned to this object which will be used by the client while mentioning the server URL. Any specific port is specified for the channel to be used.

Include System.Runtime.Remoting and write the following block of code to configure these settings on the server.

C#
RemotingConfiguration.Configure("MyRemoteServer.exe.config");

Please note that you will need to replace your config file name in place of "MyRemoteServer.exe.config" in the above statement, which will be your "AssemblyName.config".

On the Client:

Include System.Runtime.Remoting in your class and write the following code to create the proxy for the Singleton Server-side object.

C#
MyService mySingletonRem = (MyService) Activator.GetObject(typeof(MyService),
     "http://localhost:9999/MyRemoting/MyService.rem");

URL mentioned above is like ProtocolUsed://ServerAddress:PortNumber/ApplicationName/ObjectUri

SingleCall

Whenever a new call is received, a new instance of the Server-side object is created and reference is passed to the client. Therefore, for each call to the server, the client gets a new instance of the object.

To create SingleCall objects, everything will be same as in case of Singleton objects as mentioned above, but mode specified in the App.Config file on the server, which will be "SingleCall" in place of "Singleton".

Client Activation

In this, the Client requests to the server for creating a new instance which can be used for multiple calls. The instance activated by a client is not used by other clients. Client-Activated objects can store state information between method calls for its specific client.

On the Server:

Mention the following settings in the "App.config" file.

ASP.NET
<configuration>
   <system.runtime.remoting>
      <application name="MyRemoting">
         <service>
            <activated type="MyRemoteService.MyService, MyRemoteService" />
         </service>
         <channels>
            <channel ref="http" port="9999" />
         </channels>
      </application>
   </system.runtime.remoting>
</configuration>

On the Client:

Include System.Runtime.Remoting and System.Runtime.Remoting.Activation and write the following block of code.

C#
object[] activateAttribute = 
              {new UrlAttribute("http://localhost:9999/MyRemoting")};
            
MyService myClientActivatedRem = 
              (MyService) Activator.CreateInstance(typeof(MyService), 
              null, activateAttribute);        

About Sample Application

The application creates all of the three types of objects of the same class. Although, in real time projects, we will rarely get a case to create all kinds of objects of the same class. I just created them for the same class to understand and compare them easily.

Each sample object maintains a counter of the number of Client calls received by it. It returns a message which includes that counter on calling a method ServeAll().

Each client creates proxies for all of the three kinds of Server-side objects on startup. There are three buttons in the client; i.e., "Singleton", "Client Activated" and "SingleCall". Clicking on the buttons, sends a call to respective kind of Server-side object. That means, on clicking "Singleton" button, client calls the method ServeAll of the "Singleton" object.

Running Sample Application

  1. To run the demo, unzip all the demo files to a folder. Now, you can see there are two folders, one is MyRemoteServer and the another one is MyRemoteClient.
  2. Now, start the server by executing the file "MyRemoteServer.exe" in the MyRemoteServer folder.
  3. Start a client by executing the file "MyRemoteClient.exe" in the MyRemoteClient folder.
  4. Start another client by executing the file "MyRemoteClient.exe".
  5. Now, click on the buttons "SingleCall", "Singleton" and "Client Activated", one-by-one on both the clients.
  6. You will notice the following results.
    • On clicking "SingleCall", the Server-side object will always say that "I have received 1 Client Requests so far.". Though, the number of SingleCall requests sent from the client increases on every click (This is reflected on the lower part of the window). This is due to the fact that each method call from the client is served by a new Server-side object in case of SingleCall objects.
    • On clicking "Client Activated", the Server-side object says that "I have received X Client Requests so far.", where X will be same as the number of ClientActivated requests sent from a particular client. That means, if first client has sent three requests to Client Activated object, that object will say "I have received 3 Client Requests so far.", no matter how many requests are sent by second client, as clients do not share their ClientActivated objects with other clients.
    • On clicking "Singleton", the Server-side object says that "I have received X Client Requests so far.", where X will be the sum of number of Singleton requests sent from all the clients. That means, if first client has sent three requests to Singleton object and second client has sent 6 requests, that Server-side object will say "I have received 9 (i.e. 3 + 6) Client Requests so far.". This is due to the fact that both of the clients share the same Server-side Singleton object.

Inside of the Sample Application

Following is Service class whose objects are exposed to the clients. Please note that it is derived from MarshalByRefObject.

C#
using System;

namespace MyRemoteService
{
    /**********************************************************
        The objects of this class will be made available to 
        the clients thru .NET remoting. 
    **********************************************************/
    
    public class MyService: MarshalByRefObject
    {
        private int countRequests;

        //This method returns a message which includes the number of 
        //client requests received by the current instance of the class.
        public string ServeAll()
        {
            return "I have received " 
                + ++countRequests + " Client requests so far.";
        }
    }

}

The App.Config file on the server is shown below. See, it has entries for all the three types of objects. All of them are of same class i.e., MyRemoteService.MyService.

ASP.NET
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.runtime.remoting>
        <application name="MyRemoteService">
            <service>
                <wellknown
                    mode="Singleton"
                    type="MyRemoteService.MyService, MyRemoteService"
                    objectUri="MySingleton.rem"
                />
                <wellknown
                    mode="SingleCall"
                    type="MyRemoteService.MyService, MyRemoteService"
                    objectUri="MySingleCall.rem"
                />
                <activated
                    type="MyRemoteService.MyService, MyRemoteService"
                />
            </service>
            <channels>
                <channel ref="http" port="8989"/>
            </channels>
        </application>
    </system.runtime.remoting>
</configuration>

The server is written like this:

C#
using System;
using System.Runtime.Remoting;

namespace MyRemoteServer
{
    /**********************************************************
        This class configures the channel to publish 
        the service thru .NET remoting
    ***********************************************************/

    class RemoteServer
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main(string[] args)
        {
            RemotingConfiguration.Configure("MyRemoteServer.exe.config");

            Console.WriteLine("Listening for requests. Press Enter to exit...");

            Console.ReadLine();
        }
    }
}

The client has three member variables defined:

C#
MyService myClientActivatedRem;
MyService mySingleCallRem;
MyService mySingletonRem;

The App.Config on the client is shown below:

ASP.NET
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <appSettings>
        <add key="MyRemoteSingletonServiceUrl" 
            value="http://localhost:8989/MyRemoteService/MySingleton.rem"/>
        <add key="MyRemoteSingleCallServiceUrl" 
            value="http://localhost:8989/MyRemoteService/MySingleCall.rem"/>
        <add key="MyRemoteClientActivatedServiceUrl" 
            value="http://localhost:8989/MyRemoteService"/>
    </appSettings>
</configuration>

The proxies are created on client load.

C#
private void Client_Load(object sender, System.EventArgs e)
{

    //Initialize Singleton object proxy
    string mySingletonUrl = ConfigurationSettings.AppSettings
        ["MyRemoteSingletonServiceUrl"];
            
    mySingletonRem = (MyService) 
        Activator.GetObject(typeof(MyService), 
        mySingletonUrl);

    //Initialize SingleCall object proxy
    string mySingleCallUrl = ConfigurationSettings.AppSettings
        ["MyRemoteSingleCallServiceUrl"];
            
    mySingleCallRem = (MyService) 
        Activator.GetObject(typeof(MyService), 
        mySingleCallUrl);


    //Initialize ClientActivated object proxy
    string myClientActivatedUrl = ConfigurationSettings.AppSettings
        ["MyRemoteClientActivatedServiceUrl"];
            
    object[] activateAttribute = 
        {new UrlAttribute(myClientActivatedUrl)};        
            
    myClientActivatedRem = 
        (MyService) Activator.CreateInstance(typeof(MyService), null,
        activateAttribute);        

}

The click events of the three buttons have the following respective methods attached:

C#
private void btnSendRequest_Click(object sender, System.EventArgs e)
{
    //Send a request to Singleton object

    //Increment and Refresh the number of requests 
    //to Singleton object
    lblSingleton.Text = ((int) ++requestSingletonCount).ToString();
            
    //Display the Response received from the server
    //from Singleton object 
    txtSingleton.Text = mySingletonRem.ServeAll();
}

private void btnSendSingleCallRequests_Click(object sender, System.EventArgs e)
{
    //Send a request to SingleCall object

    //Increment and Refresh the number of requests 
    //to SingleCall object
    lblSingleCall.Text = ((int) ++requestSingleCallCount).ToString();
            
    //Display the Response received from the server
    //from SingleCall object 
    txtSingleCall.Text = mySingleCallRem.ServeAll();        
}

private void btnClientActivated_Click(object sender, System.EventArgs e)
{
            
    //Send a request to ClientActivated object

    //Increment and Refresh the number of requests 
    //to ClientActivated object
    lblClientActivated.Text = ((int) ++requestClientActivatedCount).ToString();

    //Display the Response received from the server
    //from ClientActivated object 
    txtClientActivated.Text = myClientActivatedRem.ServeAll();        
}

Few Points to be mentioned

  • This article covers only MBR (MarshalByReference). MarshalByObject is not taken into account in this article.
  • Recycling of Server-side objects due to Lease-Expiry is not considered to leave the article simpler.
  • There are multiple ways to do what has been done. Only the method used in the Sample Application is mentioned in the article.

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


Written By
Web Developer
India India
yogesh is currently working as a Software Consultant in New Delhi, India.

He had lived some wonderful years of his life in Chandigarh .

Comments and Discussions

 
GeneralMy vote of 5 Pin
Petr Abdulin27-Nov-11 17:04
Petr Abdulin27-Nov-11 17:04 
GeneralMy vote of 5 Pin
Saumitra Kumar Paul20-Jul-11 22:53
Saumitra Kumar Paul20-Jul-11 22:53 
QuestionGreat and Simple example Pin
brother985-Sep-06 6:59
brother985-Sep-06 6:59 
QuestionWindows Service Call Pin
Surya IG22-Aug-06 21:15
Surya IG22-Aug-06 21:15 
GeneralSources where not properly working Pin
d125-Oct-05 4:12
d125-Oct-05 4:12 
GeneralRe: Sources where not properly working Pin
Javed Akhter Siddiqui5-Oct-05 20:13
Javed Akhter Siddiqui5-Oct-05 20:13 
Hi D12,

First of All...Welcome to the world of Programming Smile | :) !!!

I found the problem with your source code.

Listen... When we include App.config file in a project and compile it, the App.config file gets copied to the Debug/Release folder, and RENAMED TO THE ASSEMBLYNAME.config.

I renamed the App.config file, which was present in your Debug folder to MyRemoteClient.exe.config, and then executed your client and it worked well.

I have not configured the client from the App.config file. I just have the URLs stored in that file, which I used to create the proxies in the code.

Please let me know, if you still have any problems.

Wish you All the very best for a successful Programming career!

Javed.


[Never believe on just your eyes, there is a lot more than what you can see.]
GeneralRe: Sources where not properly working Pin
d126-Oct-05 7:30
d126-Oct-05 7:30 
GeneralRemoting / Interface / app.config Pin
hootsman25-Jul-05 5:45
hootsman25-Jul-05 5:45 
GeneralRe: Remoting / Interface / app.config Pin
Javed Akhter Siddiqui26-Jul-05 22:13
Javed Akhter Siddiqui26-Jul-05 22:13 
GeneralRe: Remoting / Interface / app.config Pin
hootsman26-Jul-05 22:23
hootsman26-Jul-05 22:23 
GeneralRe: Remoting / Interface / app.config Pin
Javed Akhter Siddiqui26-Jul-05 22:37
Javed Akhter Siddiqui26-Jul-05 22:37 
GeneralRe: Remoting / Interface / app.config Pin
hootsman26-Jul-05 22:45
hootsman26-Jul-05 22:45 
GeneralRe: Remoting / Interface / app.config Pin
hootsman4-Aug-05 2:20
hootsman4-Aug-05 2:20 
GeneralRe: Remoting / Interface / app.config Pin
Javed Akhter Siddiqui11-Aug-05 21:23
Javed Akhter Siddiqui11-Aug-05 21:23 
GeneralRe: Remoting / Interface / app.config Pin
hootsman12-Aug-05 0:36
hootsman12-Aug-05 0:36 
GeneralRe: Remoting / Interface / app.config Pin
Javed Akhter Siddiqui12-Aug-05 0:40
Javed Akhter Siddiqui12-Aug-05 0:40 
GeneralRe: Remoting / Interface / app.config Pin
hootsman12-Aug-05 1:51
hootsman12-Aug-05 1:51 
GeneralPassing reference to remote object to another remote client Pin
lopata6-Apr-05 23:05
lopata6-Apr-05 23:05 
GeneralRe: Passing reference to remote object to another remote client Pin
Javed Akhter Siddiqui7-Apr-05 0:19
Javed Akhter Siddiqui7-Apr-05 0:19 
GeneralRe: Passing reference to remote object to another remote client Pin
lopata7-Apr-05 1:06
lopata7-Apr-05 1:06 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.