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
