Friday, March 20, 2015

Building .NET Remoting sample (Step by Step)


I am new to .Net and for one of my projects I had to use .NET Remoting. It was bit hard to find an end to end sample for a beginner even though there are code snippets describing each functionality. So I felt that it will be useful to share this with you.

I am going to give step by step details so that someone who is not familiar with visual studio can also follow and build the sample without any issue. (I am going to use visual studio which is most widely used IDE for .NET)

.NET Remoting is a mechanism that is used to access the remote services across network. (If you are familiar with WebServices the requirement which Remoting fulfills is similar to a WebService. But Remoting works with remote objects)

We are going to implement a simple chat service using .NET Remoting. We will need to implement 3 modules for this. 
  • Shared Library
  • Server side implementation
  • Client side implementation 


Implementing Shared Library

 
We will first create the shared library because both the client module and the server module is going to need it.
The shared library is used to define the remote objects that one party is going to expose to the other party. In our chat example we will need a remote object that server expose to client which allows sending messages. And another object that client expose to server which allows receiving messages. (All this will be very clear when you start building the project, so don’t worry  )
 
So let’s start creating the project.
 
File > New > Project
Select ‘Class Library’ and give the name as ‘ChatLib’ in the field below.





We need to have 2 Interfaces for the two remote objects exposed by the server and client. So let’s create two classes ClientLib and ServerLib in our Chat lib project.

In solution explorer, right click on ChatLib
Add > New Item > Interface
And give the name for the interface in the textbox below. (In this sample I am going to use IService for the interface name)






Now add the methods that we are going to expose
Register
SendMessage


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ChatLib
{
    public interface IService
    {
        void register(string userName, string url);
        void sendMessage(string userName, string msg);
    }
}


Create interface IClientService as same as above and add the method
receiveMessage


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ChatLib
{
    public interface IClientService
    {
        void receiveMessage(string sender, string msg);
    }
}


Now you are done with the ChatLib component

Server Side Implementation

Now lets add the server side code. For this do right click on solution




Add > New Project > Console App
And give the name as ServerApp




The new project will be visible along with ChatLib under solution view.

Since we are going to have the implementation of the IService in this module we need to add ChatLib as a reference to our new project. To do that right click on ServerApp

Add Reference > Solution > Projects
Tick ChatLib project which is under Solutions > Projects

We need one more reference
Assemblies > Framework
Tick System.Runtime.Remoting




Here is the code for ServerApp (to make it easy I am going to add the whole code to one file here)


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

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

namespace ServerApp
{
    class Program
    {
        static void Main(string[] args)
        {
            TcpChannel channel = new TcpChannel(9443);
            ChannelServices.RegisterChannel(channel, true);
            RemotingConfiguration.RegisterWellKnownServiceType(typeof(Server),
                "ChatServerService", WellKnownObjectMode.Singleton);

            System.Console.WriteLine("Server...... press any key");
            System.Console.ReadLine();
        }
    }

    public class Server  : System.MarshalByRefObject, IService
    {
        public Dictionary users = new Dictionary();
        public TcpChannel channel;

        public Server()
        {
            channel = new TcpChannel();
        }
        

        public void register(string userName, string port)
        {
            users.Add(userName, port);
            Console.WriteLine("user added: " + userName);     
        }

        public void sendMessage(string sender, string msg)
        {
            Console.WriteLine("msg : " + msg + " received from " + sender);

            foreach(var item in users)
            {
                //send msg to all clients 
                IClientService clientService = (IClientService)Activator.GetObject(typeof(IClientService),
                            "tcp://localhost:" + item.Value + "/ChatClientService");
                if (item.Key != sender)
                    clientService.receiveMessage(sender, msg);
            }
        }
    }
}


Now as the same way you created the ServerApp, create another console application for the ClientApp too and add the same references (ChatLib and System.Runtime.Remoting )


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ChatLib;
using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;

namespace ClientApp
{
    class Program 
    {
        static string userName;

        static void Main(string[] args)
        {
            Console.WriteLine("Enter username:");
            userName = Console.ReadLine();
           
            Console.WriteLine("Enter port:");
            string port = Console.ReadLine();

            Program program = new Program();
            program.register(port);

            Console.WriteLine("Now you can send messages");
            program.sendMessage();
            Console.ReadLine();
        }

        public void register(string port)
        {
            TcpChannel clientChannel = new TcpChannel(Convert.ToInt32(port));
            ChannelServices.RegisterChannel(clientChannel, true);

            ClientService clientLib = new ClientService();
            RemotingServices.Marshal(clientLib, "ChatClientService", typeof(ClientService));

            IService service = (IService)Activator.GetObject(typeof(IService),
               "tcp://localhost:9443/ChatServerService");

            service.register(userName, port);
            
        }

        public void sendMessage()
        {
            Console.WriteLine("mmmmm");
            IService service = (IService)Activator.GetObject(typeof(IService),
               "tcp://localhost:9443/ChatServerService");
            
            while (true)
            {
                Console.WriteLine("me:");
                string msg = Console.ReadLine();
                service.sendMessage(userName, msg);
            }
        }
        
    }

    public class ClientService : MarshalByRefObject, IClientService
    {
        public void receiveMessage(string sender, string msg)
        {
            Console.WriteLine(sender + " : " + msg);
        }
    }
}

OK... You are done with your chat application with .NET Remoting. Now you can run the application and see.





1 comment: