Remoting using interfaces and creating appdomains
This is a fun little
Visual Notepad 2 exercise which I thought I'd share with you. I wanted to know whether you could use .NET Remoting (don't run for the hills, it has its uses) with just an interface on the client and an object that implements the interface on the server.
Visual Notepad provides a great way to play with stuff like this. But if I want to play with remoting, I really want two processes or at least two appdomains. Fortunately, it's actually pretty easy to spin up an extra appdomain, so my idea was this: Create a new appdomain and run the remoting server inside it (using HTTP on port 8085). Then we'll call the server setting up the remoting client in the default appdomain.
Everything's in one file which you can
download if you like. This is what it looks like:
using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Http;
public class Test
{
public const int ClientPort = 8085;
public const int ServerPort = 8085;
public static void Main()
{
// Show the name of this appdomain
Console.WriteLine("This message is from the '" + AppDomain.CurrentDomain.FriendlyName + "' appdomain");
// Create a new appdomain called "sub domain"
AppDomain subDomain = AppDomain.CreateDomain("sub domain");
// Start the remoting server in our new appdomain
Server server = (Server) subDomain.CreateInstanceAndUnwrap("visnotepadapp", "Server");
// Create a remoting client in this appdomain
HttpChannel chan = new HttpChannel();
ChannelServices.RegisterChannel(chan, false);
// Note that we only use the interface here - no instance!
IBoo remoteBoo = (IBoo) Activator.GetObject(typeof(IBoo), "Http://localhost:" + ClientPort.ToString() +"/boo");
// call our remote boo object in the other appdomain
remoteBoo.Boo();
Console.ReadLine();
}
}
public interface IBoo
{
void Boo();
}
public class ConcreteBoo : MarshalByRefObject, IBoo
{
public void Boo()
{
Console.WriteLine("Boo! from the '" + AppDomain.CurrentDomain.FriendlyName + "' appdomain");
}
}
public class Server : MarshalByRefObject
{
public Server()
{
HttpChannel chan = new HttpChannel(Test.ServerPort);
ChannelServices.RegisterChannel(chan, false);
RemotingConfiguration.RegisterWellKnownServiceType(
typeof(ConcreteBoo), "boo", WellKnownObjectMode.SingleCall);
// Show the name of this appdomain
Console.WriteLine("The server has started in the '" + AppDomain.CurrentDomain.FriendlyName + "' appdomain");
}
}

Cool! But, if you're like me - you like to be sure that the remoting framework is in use and that the comms are indeed using Http across the network (even if it is all localhost).
First, I fired up
Process Explorer by the awesome guys at
SysInternals. Just double click on your process and select the TCP tab - process explorer will show you what ports and protocols your process is using.

You can see that visnotepadapp.exe is listening on port 8085, as expected. But I want to go one better, I want to see the traffic crossing the wire and there's a very cool way of doing this using a tool that really deserves a post all of its own (not that process explorer doesn't!).
TcpTrace
TcpTrace is an awesome little tool by the guys at
Pocket Soap. The idea is simple. You specify a port on which TcpTrace listens and another port to which it should forward any packets it receives - like a HTTP proxy only simpler.
If we want to capture traffic used by our app we need the client and the server to use different ports so that TcpTrace can squeeze in the middle.
Let's change the client to use port 8888:
public const int ClientPort = 8888; // was 8085
Now start TcpTrace and set the "Listen On Port #" to 8888, the "Destination Server" to localhost and the "Destination Port #" to the same port as our remoting server, 8085.

Now run the example application and watch the traffic flow by...

Sweet.