Wednesday, December 12, 2007

C# Remoting with a simple example

Remoting is an infrastructure that allows the developer to use remote objects. Remote objects are objects that are based (or instantiated) outside of the caller's Application Domain or in other words we can say Remoting is a framework built into Common Language Runtime (CLR) in order to provide developers classes to build distributed applications and wide range of network services. Remoting provides various features such as Object Passing, Proxy Objects, Activation, Stateless and Stateful Object, Lease Based LifeTime and Hosting of Objects in IIS.
Here I’m presenting a simple client/server based application in order to provide you easy and fast hands on Remoting.
Problem statement:
TicketServer holds information about the ticket status of a movie theater. A client needs to know the status of a ticket. Establish a connection between the client and the server so that client gets the information needed.
Solution:
A method called GetTicketStatus is defined in the server space. This method returns the status of the ticket. The server publishes this method which can be used by any client. The server listens to port 9998 over TCP. The client invokes the published method and gets the ticket status.
Implementation:
An interface MovieTicketInterface is defined which contains the GetMovieTicket method signature. This interface is implemented by MovieTicket class. The method GetMovieTicket is also implemented.
The server TicketServer registers the MovieTicket class as a remoting service. It listens to the port 9998 and waits for communication from any client.
The client creates an object of type MovieTicketInterface as a remoting object. As a part of this step, the communication between the server and the client over TCP on port number 9998 is established. It then invokes the method GetTicketStatus and gets the status.
Source code:

Server part:
1. Create a Console Application named TicketServer.
2. Add System.Runtime.Remoting as a reference to the project.
3. Replace the existing code in Class.cs with the following code and build the project.

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

class Program
{
static void Main(string[] args)
{ TicketServer();
}
static void TicketServer()
{ Console.WriteLine("Ticket Server started...");
TcpChannel tcpChannel = new TcpChannel(9998); ChannelServices.RegisterChannel(tcpChannel); Type commonInterfaceType = Type.GetType("MovieTicket"); RemotingConfiguration.RegisterWellKnownServiceType(commonInterfaceType, "MovieTicketBooking", WellKnownObjectMode.SingleCall); System.Console.WriteLine("Press ENTER for quiting"); System.Console.ReadLine();
}
}

public interface MovieTicketInterface
{
string GetTicketStatus(string stringToPrint);
}
public class MovieTicket : MarshalByRefObject, MovieTicketInterface
{
public string GetTicketStatus(string stringToPrint)
{
string returnStatus = "Ticket Confirmed"; Console.WriteLine("Enquiry for {0}", stringToPrint);
Console.WriteLine("Sending back status: {0}", returnStatus); return returnStatus;
}
}

Client side:

1. Create a Console Application named Client.

2. Add System.Runtime.Remoting and Server.exe [See Note 1] as references to the project.

3. Replace the existing code in Class.cs with the following code and build the project.

using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
class MyClient
{
public static void Main()
{
TcpChannel tcpChannel = new TcpChannel();
ChannelServices.RegisterChannel(tcpChannel); Type requiredType = typeof(MovieTicketInterface); MovieTicketInterface remoteObject = (MovieTicketInterface)Activator.GetObject(requiredType, "tcp://localhost:9998/MovieTicketBooking");

Console.WriteLine(remoteObject.GetTicketStatus("Ticket No: 3344"));
}
}
Execution:

1. Execute Server.exe

2. Execute Client.exe

You will see the appropriate messages on the client side and the remote side.

Note 1: If you are using Visual Studio 2003, you cannot add a reference to an exe file. Make a copy of Server.exe, rename it to Server.dll and this can be added as a reference in your client project.

Note 2: If you are using Visual Studio 2003, and you are getting error The type or namespace name> 'Tcp' does not exist in the class or namespace 'System.Runtime.Remoting.Channels' (are you missing an assembly> reference) then do remember that the "using" statements are merely a convenience to eliminate typing long namespace strings, they do not pull in the requisite assemblies. You must add the assembly reference of System.Runtime.Remoting by going to the Project menu and choosing Add Reference.