Remoting is a .net native method of communicating between application domains. Remoting is typically used under the following circumstances:

  • Both endpoints are native .net.
  • Both endpoints are inside an organisation, as opposed to an internet applicaition.

If the application is internet based and the client platfforms are either unknown or known to be something other that .net then SOAP based web services are typically a better choice. For additional information on how to choose between Web Services and Remoting, start here.

Remoting essentially building a class that can be Marshalled either by reference or by value. Marshalling by reference (the most common form of marshalling used with remoting), establishes a proxy, transparent or otherwise, on the client which takes all method calls on the remoted component, and then sends them back to the server where they are processed and responds to the client via the proxy. This is a complete over simplificaiton of the process and there is a great article from MSDN magazine that expliains it all here.

In it’s simplest form, remoting requires 3 key pieces: the hosting server, the client and the class being remoted. To make the implementation simpler on the client side, and loosely couple the client and server I will introduce another piece which is the ISimpleMaths interface.

ISimpleMaths

ISimpleMaths is an interface that defines four methods, Add, Subtract, Multiply and Divide in the file ISimpleMaths.cs.

using System;

public interface ISimpleMaths
{
	int Add(int x, int y);
	int Subtract(int x, int y);
	int Multiply(int x, int y);
	double Divide(int x, int y);
}

This interface is compiled into an assembly (ISimpleMaths.dll), which both the server and client compile against, removing the need for the client to compile directly against the server object.

The server object

The heavy lifting of this sample is implemented on the server in the MathsServer class. The MathsServer class inherits from ISimpleMaths and MarshalByRefObject, other than that, this is a basic class that provides methods to perform the simple maths operations. This class is saved in the MathsServer.cs file and compiled into MathsServer.dll with a reference to ISimpleMaths.dll.

using System;

public class MathsServer: MarshalByRefObject, ISimpleMaths
{
	public MathsServer()
	{
		Console.WriteLine("MathServer Constructed.");
	}

	public int Add( int x, int y)
	{
		Console.WriteLine("Adding {0} and {1}.",x,y);
		return x+y;
	}

	public int Subtract( int x, int y)
	{
		Console.WriteLine("Subtracting {0} from {1}.",x,y);
		return x-y;
	}

	public int Multiply( int x, int y)
	{
		Console.WriteLine("Multiplying {0} and {1}.",x,y);
		return x*y;
	}

	public double Divide( int x, int y)
	{
		Console.WriteLine("Dividing {0} by {1}.",x,y);
		return (double)x/(double)y;
	}
}

The Remoting Server

The remoting server itself is very simple, it opens up a TCP channel, instantiates an instance of the MathsServer class and then marshals that instance ready to be invoked by a client. The RemotingServer.cs file is compiled into RemotingServer.exe and links in MathsServer.dll as well as the appropriate remoting dll.

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

class RemotingServer
{
	static int Main ()
	{
		// Use port 1122 for TCP communications.
		// In a real applicaiton this would be a config file setting.
		int TCP_PORT = 1122; 

		// Open up the Remoting TCP Channel on
		Console.WriteLine("Starting Server");
		TcpChannel ch = new TcpChannel(TCP_PORT);
		ChannelServices.RegisterChannel (ch);

		// Instantiate the MathsServer object
		MathsServer Server = new MathsServer();

		// Marshall the MathsServer object so it can be used
		RemotingServices.Marshal(Server,"maths.rem");

		Console.WriteLine("Server Running ...");
		Console.WriteLine("Press [Enter] to exit.");

		// When someone hits enter shut the server down.
		Console.ReadLine();
		ch.StopListening (null);

		// Retun an exit code of 0 as per convention.
		return 0;
	}
}

The Client

The final piece of the sample is the client.

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

class RemotingClient
{
	public static int Main()
	{
		TcpChannel ch = new TcpChannel(0);
		ChannelServices.RegisterChannel (ch);

		object RemoteObject = Activator.GetObject(typeof(ISimpleMaths),
						"tcp://localhost:1122/maths.rem");
		ISimpleMaths MathsSrv = (ISimpleMaths)RemoteObject;

		//Add something
		int bob = MathsSrv.Add(1,2);
		Console.WriteLine("Adding 1 and 2 result is :{0}",bob);

		// Subtract something
		bob = MathsSrv.Subtract(2,1);
		Console.WriteLine("Subtract 1 from 2 result is :{0}",bob);

		//Add something
		bob = MathsSrv.Multiply(1,2);
		Console.WriteLine("Multiplying 1 and 2 result is :{0}",bob);

		// Divide something
		double tom = MathsSrv.Divide(4,2);
		Console.WriteLine("Dividing 4 and 2 result is :{0}",tom);

		//Return 0 as per convention
		return 0;
	}
}

Building the Sample

This sample can be easily built on any machine with either Mono 1.01 or any version of the .Net SDK installed.
On a machine with mono, build the sample as follows:

mcs /t:library ISimpleMaths.cs
mcs /t:library /r:ISimpleMaths.dll MathsServer.cs
mcs /r:MathsServer.dll /r:System.Runtime.Remoting.dll RemotingServer.cs
mcs /r:ISimpleMaths.dll /r:System.Runtime.Remoting.dll MathsClient.cs

On windows, you will need to use the .net Command prompt to build like this:

csc /t:library ISimpleMaths.cs
csc /t:library /r:ISimpleMaths.dll MathsServer.cs
csc /r:MathsServer.dll /r:ISimpleMaths.dll RemotingServer.cs
csc /r:ISimpleMaths.dll MathsClient.cs

If it all works as planned

Hopefully everything should have compiled OK and you can open up two terminal windows.. In the first start there server RemotingServer.exe and you should see the following output.

Starting Server
MathServer Constructed.
Server Running ...
Press [Enter] to exit.

The client window should see it’s work being very generiously being performed by a server. There should be some output as follows.

Adding 1 and 2 result is :3
Subtract 1 from 2 result is :1
Multiplying 1 and 2 result is :2
Dividing 4 and 2 result is :2

So there you have it, a simple working example of .net remoting, Interestingly whilst writing this article I pointed my windows machine at my Powerbook and got the following division result.

Dividing 4 and 2 result is :3.16202013338398E-322

This shows that it always pays to check your results are what they should be. Without investigating this I would guess that this appears to be a endianness problem.

Additional Information

An Introduction to the .net remoting framework

MSDN: .NET Remoting A technical overview.

I was looking for some reference information for recommending to a customer how to choose between Web Services or Remoting to connect to an external server or components on another physical server of a three tier architecture. If you are faced with such a decision I would recommend starting your research with these two MSDN articles:

ASP.NET Web Services or .NET Remoting: How to Choose
Performance Comparison: .NET Remoting vs. ASP.NET Web Services