.NET Remoting

Last Updated: 2001

 

Channels:

Two basic methods:

Class Access:

MBR Activation:

  Server Activation (where the server controls the lifespan of the object)

  Client Activation (where the client controls the lifespan of the object)

  Configuration:

The configuration file used with the new command can be loaded using RemotingConfiguration.Configure(...). Multiple configuration files can be use at once.

Alternatively, remoting can be configured programmatically using ChannelServices.RegisterChannel(...) and the RemotingConfiguration object (for examples, see source code later)

MBV & MBR Sample

This requires three projects (which can all be placed in the same project):

  1. The project containing the class to be remoted
    This is in a separate assembly (dll) - and hence separate project - because:
        (a) Its more convenient
        (b) We need to reference it from both the client and the server and if we included it in either of those it would be in an EXE and not a DLL (it has to be a DLL for us to add a reference to it).
     
  2. The project containing the client code
     
  3. The project containing the server code
    A server must be running to register the channels required. This doesn't mean we write code on the server to create and/or return actual objects but we do have to write code to register the objects the server will handle and on what channels / ports it will be listening.

The Remoted Class Project:

[This sample is based on a C# class library template to ensure we get a DLL. For the purposes of this example, either call the project RemoteTest, change the output name to RemoteTest or change all later references to RemoteTest to whatever you called this project]

using System;
using
System.Diagnostics;

namespace
DavesRemoteObject {
   
// The class that will be remoted (by reference since we inherit from MarshalByRefObject)
   
public class DaveMath : MarshalByRefObject {
       
public int Add2ANumbers (ANumber number1, ANumber number2) {
           
return number1.Value + number2.Value;
        }

        // A method to indicate where we are executing
       
public void WhereAmI() {
            Console.WriteLine("WhereAmI was executed in: " + Process.GetCurrentProcess().ProcessName.ToString());
        }
}

// A class that we'll pass to and from the remoted object (by value as we've marked it Serializable]
[Serializable]
public class ANumber {
   
// Property to hold the number & its accessors
   
private int _Value;
   
public int Value {
       
get {return _Value;}
       
set {_Value = value;}
    }
}
}

The Remote Server Project

[The name of the project here doesn't matter as we will be listening on a channel for a specific URI. This project should be based on the C# Console template so that we can easily output text.

The following references need to be added to the project:

]

using System;
using
System.Runtime.Remoting;
using
System.Runtime.Remoting.Channels;
using
System.Runtime.Remoting.Channels.Tcp;

namespace
RemotingTestServer {

    class TestServer {
        [STAThread]
       
static void Main(string[] args) {
           
// Initialise a channel on port 8085
            TcpChannel chan =
new TcpChannel(8085);

            // Register the channel so the client can use it
            ChannelServices.RegisterChannel(chan);

            // Register the class (aka Type) so the the client can use it
            //     The parameters  for RemotingConfiguration.RegisterWellKnownType are:
            //         Full Type Name of object followed by comma followed by Assembly (dll) name
            //             (e.g. "ServerClassValue.HelloServer, RemoteTest")
            //         Object Endpoint name (used by client to request the object in the URI)
            //         Object Mode (from WellKnownObjectMode enums)

            Type objType = Type.GetType("DavesRemoteObject.DaveMath, RemoteTest");
            RemotingConfiguration.RegisterWellKnownServiceType(
                objType,
                "DaveMathEndPoint",
                WellKnownObjectMode.SingleCall);

            // Prevent the server shutting down till we are finished with it
           
Console.WriteLine("Press <Enter> to terminate server");
            Console.ReadLine();
        }
    }
}

The Client Project

[Again, project name does not matter, but again, make it a C# Console application so that we can easily output text. The required references are the same as for the server, i.e.:

]

using System;
using
System.Runtime.Remoting;
using
System.Runtime.Remoting.Channels;
using
System.Runtime.Remoting.Channels.Tcp;
using
DavesRemoteObject;

namespace RemotingTestClient {

class TestClient {
    [STAThread]
   
static void Main(string[] args) {
        Console.WriteLine("Client\n======\n");
        Console.WriteLine("Press <Enter> once server has started.");
        Console.ReadLine();

        // Initialise the channel we'll use to talk to the server
        TcpChannel chan =
new TcpChannel();
        ChannelServices.RegisterChannel(chan);

        // Do the maths locally first
        DaveMath LocalDaveMath =
new DaveMath();
        ANumber number1 =
new ANumber();
        number1.Value = 2;
        ANumber number2 =
new ANumber();
        number2.Value = 2;
        Console.WriteLine("Local Math: 2 + 2 = " + LocalDaveMath.Add2ANumbers(number1, number2));
        LocalDaveMath.WhereAmI();

        // Do the maths remotely
        DaveMath RemoteDaveMath = (DaveMath) Activator.GetObject(
           
typeof(DaveMath), "tcp://localhost:8085/DaveMathEndPoint");
       
if (RemoteDaveMath == null) Console.WriteLine("Couldn't find server?");
       
else {
            Console.WriteLine("Remote Math: 2 + 2 = " + RemoteDaveMath.Add2ANumbers(number1, number2));
            RemoteDaveMath.WhereAmI();
            Console.WriteLine("Method executed, check server window for 'WhereAmI' output.");
       }

        // All done
       Console.WriteLine("Press <Enter> to exit");
       Console.ReadLine();
    }
}
}