Remoting Chat Application

Concept

The application is designed using the .NET remoting framework 1.0. .NET remoting provides a very powerful framework for distributed applications. When you design a chat application, you need to maintain the state of the client at the server side. That means the server and clients must be in continuous contact. By using CAO (client activated objects), it is not possible to maintain state at the server side. Server-activated objects with singleton (a single server object serving all clients) design is the best methodology to develop a chat application. The application uses server-activated singleton object. A shared interface approach is used for communication between the server and client. This prevents the client from directly creating a server object.

Implementation

There are three projects in the application: ChatClient, ChatServer, and ChatMediator. ChatServer is a normal remoting server that runs on TCP (5678) and HTTP (8888) channels. The ChatMediator project is a common interface shared across client and server. ChatClient is the client that can connect to the server either by a TCP or HTTP channel. Following are the details of each project and how they work.

ChatServer

ChatServer is the simple remoting server. It also contains an internal class that derives from MarshalByRef and implements the common interface shared across client and server.

Here is the code of Server class.

/***************************************************************/
class Server
   {
      private HttpChannel htc;
      private TcpChannel tcc;
      private int httpPortNumber = 8888;
      private int tcpPortNumber = 5678;

      public Server()
      {
         // Register Http channel
         SoapClientFormatterSinkProvider scl = null;
         SoapServerFormatterSinkProvider ssr =
            new SoapServerFormatterSinkProvider();
         ssr.TypeFilterLevel = TypeFilterLevel.Full;
         IDictionary id = new Hashtable();
         id["port"] = httpPortNumber;
         id["typeFilterLevel"] = TypeFilterLevel.Full;
         id["name"] = System.Guid.NewGuid().ToString();
         htc = new HttpChannel(id, scl, ssr);
         ChannelServices.RegisterChannel(htc);
         id.Clear();
         id = null;

         // Register Tcp channel
         BinaryClientFormatterSinkProvider bcfs = null;
         BinaryServerFormatterSinkProvider bsfs =
            new BinaryServerFormatterSinkProvider();
         bsfs.TypeFilterLevel = TypeFilterLevel.Full;
         id = new Hashtable();
         id["port"] = tcpPortNumber;
         id["typeFilterLevel"] = TypeFilterLevel.Full;
         id["name"] = System.Guid.NewGuid().ToString();
         tcc = new TcpChannel(id, bcfs, bsfs);
         ChannelServices.RegisterChannel(tcc);
         id.Clear();
         id = null;
      }

      public static void StartServer()
      {
         try
         {

RemotingConfiguration.RegisterWellKnownServiceType(typeof(Mediator),
                      "ChatServer.soap",
            WellKnownObjectMode.Singleton);
         }
         catch (RemotingException ex)
         {
            Console.WriteLine(ex.Message);
            throw new UserExceptions(ex.Message, ex);
         }
      }

   /// <summary>
   /// The main entry point for the application.
   /// </summary>
   [STAThread]
   static void Main(string[] args)
   {
      //
      // TODO: Add code to start application here
      //
      if (args != null && args.Length > 0)
      {
         Console.WriteLine(args[0]);
      }

try
      {

Console.WriteLine(
   "/********************************************************/");
Console.WriteLine("**\tWelcome to chat application developed by-:");
Console.WriteLine("**\tJayant D. Kulkarni,
                      Mahindra-British Telecom.");
        Console.WriteLine("**\tThis is server.");
        Server srs = new Server(); 
        Server.StartServer();
        Console.WriteLine("**\tServer started successfuly.");
        Console.WriteLine("**\tListening at.");
        Console.WriteLine("**\tHttpChannel: 8888 and TcpChannel:
                              5678.");

Console.WriteLine(
   "/********************************************************/\n\n");
      }
      catch (Exception ex)
      {
Console.WriteLine("Error occured. Message: " + ex.Message);
      }

      Console.ReadLine();
   }
}
Userdefined exception class
   /**************************************************************/
internal class UserExceptions : ApplicationException
   {
      internal UserExceptions(string message) : base(message)
      {
      }

internal UserExceptions(string message, RemotingException ex) :
         base(message, ex)
      {
      }
   }
   /**************************************************************/

Remoting Chat Application

This is an internal class that actually gets serialized and implements a shared interface. In this class are methods such as connect, remove, sendmessage, and so forth.

   /**************************************************************/
      [Serializable]
internal class Mediator : MarshalByRefObject, IMediator
{
   private ArrayList clientsList;
   private ArrayList privateChatClient;
   private string []errorMessages = {"User already exists"};

   public Mediator()
   {
      this.clientsList = new ArrayList();
      this.privateChatClient = new ArrayList();
   }

   #region IMediator Members

   public void ConnectToChat(IClientImplement ici)
   {
      if (ici != null)
      {
         try
         {
            // First check with the unique user
            foreach (IClientImplement icc in this.clientsList)
            {
               if (icc.UserName.CompareTo(ici.UserName) == 0)
               {
                  throw new UserExceptions(errorMessages[0]);
               }
            }

            this.clientsList.Add(ici);
            Console.WriteLine(
   "--------------------Joining of new user----------------------");
            Console.WriteLine(ici.UserName + " joined chat at: "
               + DateTime.Now.ToString());
            Console.WriteLine(
   "----------------------------------------------------------");

            foreach (IClientImplement icimp in this.clientsList)
            {
               ici.ClientList = this.clientsList;
               icimp.SendWelcomeMessageTome(ici);
            }
         }
         catch (RemotingException ex)
         {
            Console.WriteLine(ex.Message);
            Console.WriteLine(ex.StackTrace);
            throw new UserExceptions(ex.Message, ex);
         }
      }
   }

   public void SendMessageToAll(IClientImplement ici)
   {
      try
      {
         foreach (IClientImplement icimp in this.clientsList)
         {
            icimp.SendMessageTome(ici);
         }
      }
      catch (RemotingException ex)
      {
         Console.WriteLine(ex.Message);
         Console.WriteLine(ex.StackTrace);
         throw new UserExceptions(ex.Message, ex);
      }
   }

   public void RemoveMe(IClientImplement ici)
   {
      if (ici != null)
      {
         try
         {
            ArrayList temp = new ArrayList();

            Console.WriteLine(
   "\n-------------Removal of user--------------------------\n");
            foreach (IClientImplement icm in this.clientsList)
            {
               Console.WriteLine("User name: " + icm.UserName);
               if (icm.UserName.CompareTo(ici.UserName) != 0)
               {
                  Console.WriteLine("Added user name: " + icm.UserName);
                  temp.Add(icm);
               }
            }

            Console.WriteLine(ici.UserName + " left chat at: "
                              + DateTime.Now.ToString());

            foreach (IClientImplement icimp in temp)
            {
               Console.WriteLine("Sending message to: " + icimp.UserName);
               ici.ClientList = temp;
               icimp.UserLeft(ici);
            }

            this.clientsList.Clear();
            foreach (IClientImplement icm in temp)
            {
               Console.WriteLine("Updating class array list.
                                  Adding: " + icm.UserName);
               this.clientsList.Add(icm);
            }
            Console.WriteLine(
   "\n--------------------------------------------\n");
         }
         catch (RemotingException ex)
         {
            Console.WriteLine("\n\nError occured. Message:" +
                              ex.Message);
            Console.WriteLine("Stack trace: " + ex.StackTrace);
            throw new UserExceptions(ex.Message, ex);
         }
      }
   }

   public void SendPrivateMessage(IClientImplement clientObject)
   {
      try
      {
         string []strUsers = clientObject.UserName.Split('|');
         string sender = strUsers[0];
         string receiver = strUsers[1];
         Console.WriteLine(
   "-------------------Private chat section--------------");
         Console.WriteLine("Sending private message from " +
                           sender + " to " + receiver);
         Console.WriteLine("Message: " + clientObject.Message);

         foreach (IClientImplement ici in this.privateChatClient)
         {
            Console.WriteLine("UserName: " + ici.UserName +
                              " Receiver: " + ici.ReceiverName);
            clientObject.UserName = sender;
            ici.SendMessageTome(clientObject);
         }

         foreach (IClientImplement icc in this.clientsList)
         {
            if (icc.UserName.CompareTo(receiver) == 0)
            {
               clientObject.UserName = sender;
               Console.WriteLine("Sending private message to: "
                                 + icc.UserName);
               icc.SendMessageTome(clientObject);
            }
         }
         Console.WriteLine(
   "-----------------------------------------------");
      }
      catch (Exception ex)
      {
         Console.WriteLine("An error occured. Error: " + ex.Message);
      }
   }

   public void ConnectToPrivateChat(IClientImplement clientObject)
   {
      string []strUsers = clientObject.UserName.Split('|');
      string sender = strUsers[0];
      string receiver = strUsers[1];

      foreach (IClientImplement ici in this.privateChatClient)
      {
         if (ici.UserName.CompareTo(clientObject.UserName) == 0)
         {
            throw new ApplicationException("User already started
                                            private chat with the
                                            given user");
         }
      }
      
      this.privateChatClient.Add(clientObject);
      Console.WriteLine(
   "\n----------------Private chat connect--------------\n");
      Console.WriteLine("Private chat started between " + sender
                        + " and " + receiver + " at:"
                        + DateTime.Now.ToString());
   }

   #endregion

   public override object InitializeLifetimeService()
   {
      return null;
   }
}
/***************************************************************/

Remoting Chat Application

ChatMediator

This project contains two interfaces and one abstract class. One interface is a shared interface used by the client and server. Another interface is implemented by an Abstract class and used by server to send a message to the client. The interesting thing is the abstract class that will be implemented at the client side and generate events whenever a new user in joined, private chat is started, user left, and so on.

This architecture is implemented because when delegates are wrapped by some methods, the delegate needs full type information about the class that wraps the delegate. As abstract class is implementing an interface; the server sends message to all clients using the object of the interface. At the client side, when the message is received, an event is raised by the class (which is derived from abstract class) and handled in an actual Windows form application.

Shared interface

/***************************************************************/
   public interface IMediator
   {
      void ConnectToChat(IClientImplement clientObject);
      void SendMessageToAll(IClientImplement clientObject);
      void RemoveMe(IClientImplement clientObject);
      void SendPrivateMessage(IClientImplement clientObject);
      void ConnectToPrivateChat(IClientImplement clientObject);
}
/***************************************************************/

Interface used by server to send message to client

/***************************************************************/
   public interface IClientImplement
   {
      ArrayList ClientList
      {
         get;
         set;
      }

      string UserName
      {
         get;
         set;
      }

      string Message
      {
         get;
         set;
      }

      string ReceiverName
      {
         get;
         set;
      }
      void SendMessageTome(IClientImplement clientObject);
      void SendWelcomeMessageTome(IClientImplement clientObject);
      void UserLeft(IClientImplement clientObject);
   }
/***************************************************************/

An abstract class that derives from MarshalByRef and will act as a server when the server sends message to the client

/***************************************************************/
[Serializable]
public abstract class EventsManager : MarshalByRefObject,
                                      IClientImplement
   {
      #region IClientImplement Members

      public abstract string UserName
      {
         get;
         set;
      }

      public abstract ArrayList ClientList
      {
         get;
         set;
      }

      public abstract string Message
      {
         get;
         set;
      }

      public abstract string ReceiverName
      {
         get;
         set;
      }

public abstract void SendMessageTome(IClientImplement clientObject);
public abstract void SendWelcomeMessageTome(IClientImplement
                                            clientObject);
public abstract void UserLeft(IClientImplement clientObject);

      #endregion
   }
/***************************************************************/

Remoting Chat Application

ChatClient

ChatClient is a Windows application. When ChatClient.exe is run, it first shows the splash screen that introduces the developer. When the user clicks connect, the application tries to the connect to server and when connected populates the list box with the current users online.

There is an EventClass class that derives from the abstract class and has delegates that are wrapped by ChatClient. Whenever EventClass receives message, it raises an event and ChatClient accordingly takes the necessary action.

ChatClient

/***************************************************************/
   public class Form1 : System.Windows.Forms.Form
   {
      /// <summary>
      /// Required designer variable.
      /// </summary>
      private System.ComponentModel.Container components = null;
      private System.Windows.Forms.Label lblErrorMessage;
      private System.Windows.Forms.GroupBox grpClientChatBox;
      private System.Windows.Forms.RichTextBox txtMessage;
      private System.Windows.Forms.Label lblUserList;
      private System.Windows.Forms.StatusBar stsConnected;
      private System.Windows.Forms.Label lblUserName;
      private System.Windows.Forms.TextBox txtUserName;
      private System.Windows.Forms.ListBox lstUsers;
      private System.Windows.Forms.Button btnConnect;
      private System.Windows.Forms.GroupBox groupBox1;
      private System.Windows.Forms.TextBox textBox1;
      private System.Windows.Forms.Label label1;
      private System.Windows.Forms.TextBox textBox2;
      private System.Windows.Forms.Label label2;
      private System.Windows.Forms.Label label3;
      private System.Windows.Forms.GroupBox grpAuthenticate;
      private System.Windows.Forms.TextBox txtProxyPassword;
      private System.Windows.Forms.Label lblPassword;
      private System.Windows.Forms.TextBox txtProxyUserName;
      private System.Windows.Forms.Label lblUser;

      #region MyVariables

      private IMediator im = null;
      private EventsClass em = null;
      private ArrayList clientList = null;
      private System.Windows.Forms.Button btnSend;
      private System.Windows.Forms.TextBox txtSendMessage;
      private System.Windows.Forms.GroupBox grpSend;
      private System.Windows.Forms.Label lblUserCount;
      private IClientImplement iciClient = null;
      private Hashtable hsPrivateWindows = new Hashtable();
      private string httpServerUrl =
         ConfigurationSettings.AppSettings["HttpServerURL"].ToString();
      private string tcpServerUrl =
         ConfigurationSettings.AppSettings["TcpServerURL"].ToString();

      #endregion

      public Form1()
      {
         //
         // Required for Windows Form Designer support
         //
         InitializeComponent();

         //
         // TODO: Add any constructor code after
         // InitializeComponent call
         //
      }

      /// <summary>
      /// Clean up any resources being used.
      /// 
      protected override void Dispose( bool disposing )
      {
         if( disposing )
         {
            if (components != null)
            {
               components.Dispose();
            }
         }
         base.Dispose( disposing );
      }

      #region Windows Form Designer generated code
      /// <summary>
      /// Required method for Designer support - do not modify
      /// the contents of this method with the code editor.
      /// </summary>
      private void InitializeComponent()
      {
         System.Resources.ResourceManager resources =
            new System.Resources.ResourceManager(typeof(Form1));
         this.lblErrorMessage = new System.Windows.Forms.Label();
         this.grpClientChatBox = new System.Windows.Forms.GroupBox();
         this.grpSend = new System.Windows.Forms.GroupBox();
         this.lblUserCount = new System.Windows.Forms.Label();
         this.btnSend = new System.Windows.Forms.Button();
         this.txtSendMessage = new System.Windows.Forms.TextBox();
         this.txtMessage = new System.Windows.Forms.RichTextBox();
         this.lblUserList = new System.Windows.Forms.Label();
         this.stsConnected = new System.Windows.Forms.StatusBar();
         this.lblUserName = new System.Windows.Forms.Label();
         this.txtUserName = new System.Windows.Forms.TextBox();
         this.lstUsers = new System.Windows.Forms.ListBox();
         this.btnConnect = new System.Windows.Forms.Button();
         this.groupBox1 = new System.Windows.Forms.GroupBox();
         this.textBox1 = new System.Windows.Forms.TextBox();
         this.label1 = new System.Windows.Forms.Label();
         this.textBox2 = new System.Windows.Forms.TextBox();
         this.label2 = new System.Windows.Forms.Label();
         this.label3 = new System.Windows.Forms.Label();
         this.grpAuthenticate = new System.Windows.Forms.GroupBox();
         this.txtProxyPassword = new System.Windows.Forms.TextBox();
         this.lblPassword = new System.Windows.Forms.Label();
         this.txtProxyUserName = new System.Windows.Forms.TextBox();
         this.lblUser = new System.Windows.Forms.Label();
         this.grpClientChatBox.SuspendLayout();
         this.grpSend.SuspendLayout();
         this.groupBox1.SuspendLayout();
         this.grpAuthenticate.SuspendLayout();
         this.SuspendLayout();
         // 
         // lblErrorMessage
         // 
         this.lblErrorMessage.ForeColor = System.Drawing.Color.Red;
         this.lblErrorMessage.Location =
            new System.Drawing.Point(74, -112);
         this.lblErrorMessage.Name = "lblErrorMessage";
         this.lblErrorMessage.Size = new System.Drawing.Size(408, 88);
         this.lblErrorMessage.TabIndex = 10;
         // 
         // grpClientChatBox
         // 
         this.grpClientChatBox.Controls.Add(this.grpSend);
         this.grpClientChatBox.Controls.Add(this.txtMessage);
         this.grpClientChatBox.Controls.Add(this.lblUserList);
         this.grpClientChatBox.Controls.Add(this.stsConnected);
         this.grpClientChatBox.Controls.Add(this.lblUserName);
         this.grpClientChatBox.Controls.Add(this.txtUserName);
         this.grpClientChatBox.Controls.Add(this.lstUsers);
         this.grpClientChatBox.Controls.Add(this.btnConnect);
         this.grpClientChatBox.Location =
            new System.Drawing.Point(8, 104);
         this.grpClientChatBox.Name = "grpClientChatBox";
         this.grpClientChatBox.Size = new System.Drawing.Size(656, 408);
         this.grpClientChatBox.TabIndex = 8;
         this.grpClientChatBox.TabStop = false;
         this.grpClientChatBox.Text = "Client";
         // 
         // grpSend
         // 
         this.grpSend.Controls.Add(this.lblUserCount);
         this.grpSend.Controls.Add(this.btnSend);
         this.grpSend.Controls.Add(this.txtSendMessage);
         this.grpSend.Enabled = false;
         this.grpSend.Location = new System.Drawing.Point(16, 200);
         this.grpSend.Name = "grpSend";
         this.grpSend.Size = new System.Drawing.Size(368, 120);
         this.grpSend.TabIndex = 11;
         this.grpSend.TabStop = false;
         this.grpSend.Text = "Send";
         // 
         // lblUserCount
         // 
         this.lblUserCount.Location = new System.Drawing.Point(16, 88);
         this.lblUserCount.Name = "lblUserCount";
         this.lblUserCount.Size = new System.Drawing.Size(344, 23);
         this.lblUserCount.TabIndex = 13;
         // 
         // btnSend
         // 
         this.btnSend.Font =
            new System.Drawing.Font("Microsoft Sans Serif", 11F,
                                    System.Drawing.FontStyle.Bold,
                                    System.Drawing.GraphicsUnit.Point,
                                    ((System.Byte)(0)));
         this.btnSend.Location = new System.Drawing.Point(284, 24);
         this.btnSend.Name = "btnSend";
         this.btnSend.Size = new System.Drawing.Size(72, 48);
         this.btnSend.TabIndex = 5;
         this.btnSend.Text = "Send";
         this.btnSend.Click +=
            new System.EventHandler(this.btnSend_Click);
         // 
         // txtSendMessage
         // 
         this.txtSendMessage.ForeColor = System.Drawing.Color.Maroon;
         this.txtSendMessage.Location = new System.Drawing.Point(8, 24);
         this.txtSendMessage.Multiline = true;
         this.txtSendMessage.Name = "txtSendMessage";
         this.txtSendMessage.Size = new System.Drawing.Size(272, 48);
         this.txtSendMessage.TabIndex = 4;
         this.txtSendMessage.Text = "Hi!!";
         this.txtSendMessage.KeyDown +=
            new System.Windows.Forms.KeyEventHandler
            (this.txtSendMessage_KeyDown);
         // 
         // txtMessage
         // 
         this.txtMessage.Location = new System.Drawing.Point(16, 56);
         this.txtMessage.Name = "txtMessage";
         this.txtMessage.ReadOnly = true;
         this.txtMessage.Size = new System.Drawing.Size(360, 128);
         this.txtMessage.TabIndex = 10;
         this.txtMessage.Text = "
   /*********************WELCOME TO CHAT ROOM ********************/";
         // 
         // lblUserList
         // 
         this.lblUserList.BorderStyle =
            System.Windows.Forms.BorderStyle.FixedSingle;
         this.lblUserList.Font =
            new System.Drawing.Font("Microsoft Sans Serif", 11.25F,
                                    System.Drawing.FontStyle.Bold,
                                    System.Drawing.GraphicsUnit.Point,
                                    ((System.Byte)(0)));
         this.lblUserList.Location = new System.Drawing.Point(480, 24);
         this.lblUserList.Name = "lblUserList";
         this.lblUserList.Size = new System.Drawing.Size(80, 32);
         this.lblUserList.TabIndex = 9;
         this.lblUserList.Text = "Users list";
         this.lblUserList.TextAlign =
            System.Drawing.ContentAlignment.MiddleCenter;
         // 
         // stsConnected
         // 
         this.stsConnected.Location = new System.Drawing.Point(3, 383);
         this.stsConnected.Name = "stsConnected";
         this.stsConnected.Size = new System.Drawing.Size(650, 22);
         this.stsConnected.TabIndex = 8;
         this.stsConnected.Text = "Not connected...";
         // 
         // lblUserName
         // 
         this.lblUserName.Location = new System.Drawing.Point(16, 24);
         this.lblUserName.Name = "lblUserName";
         this.lblUserName.Size = new System.Drawing.Size(64, 16);
         this.lblUserName.TabIndex = 5;
         this.lblUserName.Text = "UserName: ";
         // 
         // txtUserName
         // 
         this.txtUserName.Location = new System.Drawing.Point(96, 24);
         this.txtUserName.Name = "txtUserName";
         this.txtUserName.Size = new System.Drawing.Size(192, 20);
         this.txtUserName.TabIndex = 2;
         this.txtUserName.Text = "User";
         // 
         // lstUsers
         // 
         this.lstUsers.Location = new System.Drawing.Point(424, 64);
         this.lstUsers.Name = "lstUsers";
         this.lstUsers.Size = new System.Drawing.Size(208, 303);
         this.lstUsers.TabIndex = 4;
         this.lstUsers.DoubleClick +=
            new System.EventHandler(this.lstUsers_DoubleClick);
         // 
         // btnConnect
         // 
         this.btnConnect.Location = new System.Drawing.Point(304, 24);
         this.btnConnect.Name = "btnConnect";
         this.btnConnect.TabIndex = 3;
         this.btnConnect.Text = "Connect";
         this.btnConnect.Click +=
            new System.EventHandler(this.btnConnect_Click);
         // 
         // groupBox1
         // 
         this.groupBox1.Controls.Add(this.textBox1);
         this.groupBox1.Controls.Add(this.label1);
         this.groupBox1.Controls.Add(this.textBox2);
         this.groupBox1.Controls.Add(this.label2);
         this.groupBox1.Location = new System.Drawing.Point(-190, -120);
         this.groupBox1.Name = "groupBox1";
         this.groupBox1.Size = new System.Drawing.Size(248, 96);
         this.groupBox1.TabIndex = 9;
         this.groupBox1.TabStop = false;
         this.groupBox1.Text = "Proxy authentication";
         // 
         // textBox1
         // 
         this.textBox1.Location = new System.Drawing.Point(128, 56);
         this.textBox1.Name = "textBox1";
         this.textBox1.PasswordChar = '*';
         this.textBox1.TabIndex = 3;
         this.textBox1.Text = "";
         // 
         // label1
         // 
         this.label1.Location = new System.Drawing.Point(16, 56);
         this.label1.Name = "label1";
         this.label1.TabIndex = 2;
         this.label1.Text = "Password:";
         // 
         // textBox2
         // 
         this.textBox2.Location = new System.Drawing.Point(128, 24);
         this.textBox2.Name = "textBox2";
         this.textBox2.TabIndex = 1;
         this.textBox2.Text = "ProxyUser";
         // 
         // label2
         // 
         this.label2.Location = new System.Drawing.Point(16, 24);
         this.label2.Name = "label2";
         this.label2.TabIndex = 0;
         this.label2.Text = "UserName:";
         // 
         // label3
         // 
         this.label3.ForeColor = System.Drawing.Color.Red;
         this.label3.Location = new System.Drawing.Point(268, 16);
         this.label3.Name = "label3";
         this.label3.Size = new System.Drawing.Size(396, 80);
         this.label3.TabIndex = 12;
         // 
         // grpAuthenticate
         // 
         this.grpAuthenticate.Controls.Add(this.txtProxyPassword);
         this.grpAuthenticate.Controls.Add(this.lblPassword);
         this.grpAuthenticate.Controls.Add(this.txtProxyUserName);
         this.grpAuthenticate.Controls.Add(this.lblUser);
         this.grpAuthenticate.Enabled = false;
         this.grpAuthenticate.Location = new System.Drawing.Point(4, 8);
         this.grpAuthenticate.Name = "grpAuthenticate";
         this.grpAuthenticate.Size = new System.Drawing.Size(248, 88);
         this.grpAuthenticate.TabIndex = 11;
         this.grpAuthenticate.TabStop = false;
         this.grpAuthenticate.Text = "Proxy authentication";
         // 
         // txtProxyPassword
         // 
         this.txtProxyPassword.Location = new System.Drawing.Point(128, 56);
         this.txtProxyPassword.Name = "txtProxyPassword";
         this.txtProxyPassword.PasswordChar = '*';
         this.txtProxyPassword.TabIndex = 1;
         this.txtProxyPassword.Text = "password";
         // 
         // lblPassword
         // 
         this.lblPassword.Location = new System.Drawing.Point(16, 56);
         this.lblPassword.Name = "lblPassword";
         this.lblPassword.TabIndex = 2;
         this.lblPassword.Text = "Password:";
         // 
         // txtProxyUserName
         // 
         this.txtProxyUserName.Location =
            new System.Drawing.Point(128, 24);
         this.txtProxyUserName.Name = "txtProxyUserName";
         this.txtProxyUserName.TabIndex = 0;
         this.txtProxyUserName.Text = "user";
         // 
         // lblUser
         // 
         this.lblUser.Location = new System.Drawing.Point(16, 24);
         this.lblUser.Name = "lblUser";
         this.lblUser.TabIndex = 0;
         this.lblUser.Text = "UserName:";
         // 
         // Form1
         // 
         this.AcceptButton = this.btnSend;
         this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
         this.BackColor =
            System.Drawing.Color.FromArgb(((System.Byte)(192)),
                                          ((System.Byte)(192)),
                                          ((System.Byte)(255)));
         this.ClientSize = new System.Drawing.Size(680, 525);
         this.Controls.Add(this.label3);
         this.Controls.Add(this.grpAuthenticate);
         this.Controls.Add(this.lblErrorMessage);
         this.Controls.Add(this.grpClientChatBox);
         this.Controls.Add(this.groupBox1);
         this.Icon =
            ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
         this.Name = "Form1";
         this.Text = "Form1";
         this.Closing +=
            new System.ComponentModel.CancelEventHandler(this.Form1_Closing);
         this.Load += new System.EventHandler(this.Form1_Load);
         this.Closed += new System.EventHandler(this.Form1_Closed);
         this.grpClientChatBox.ResumeLayout(false);
         this.grpSend.ResumeLayout(false);
         this.groupBox1.ResumeLayout(false);
         this.grpAuthenticate.ResumeLayout(false);
         this.ResumeLayout(false);

      }
      #endregion

      /// <summary>
      /// The main entry point for the application.
      /// </summary>
      [STAThread]
      static void Main()
      {
         Application.Run(new Form1());
      }

      private bool StartHttpServer()
      {
         bool result = false;
         IDictionary id = null;
         string uname = txtProxyUserName.Text;
         string pwd = txtProxyPassword.Text;
         ICredentials ic = null;
         try
         {
            SoapClientFormatterSinkProvider scl =
               new SoapClientFormatterSinkProvider();
            SoapServerFormatterSinkProvider ssr =
               new SoapServerFormatterSinkProvider();
            ssr.TypeFilterLevel = TypeFilterLevel.Full;

            IWebProxy proxy =
               new WebProxy("proxy.sharda.mahindrabt.com", 80);
            ic = new NetworkCredential(uname, pwd);
            proxy.Credentials = ic;

            id = new Hashtable();
            id["port"] = 0;
            id["typeFilterLevel"] = TypeFilterLevel.Full;
            id["name"] = System.Guid.NewGuid().ToString();

            HttpChannel htc = new HttpChannel(id, scl, ssr);
            ChannelServices.RegisterChannel(htc);
            this.SetChannelProxy(htc, proxy);

            this.im = (IMediator) Activator.GetObject(typeof
                      (IMediator), this.httpServerUrl);
            result = true;
         }
         catch (RemotingException ex)
         {
            MessageBox.Show(ex.Message + " Stact trace: " +
                            ex.StackTrace);
         }
         finally
         {            
         }
         return result;
      }

      private void SetChannelProxy( HttpChannel channel, IWebProxy proxy )
      {
         //get the channel data
         FieldInfo clientChannelFieldInfo =
            typeof(HttpChannel).GetField("_clientChannel",
                                         BindingFlags.Instance |
                                         BindingFlags.NonPublic);
         //cast it to httpclientchannel to get an access to
         //IWebProxy Class.
         HttpClientChannel clientChannel =
            (HttpClientChannel) clientChannelFieldInfo.GetValue(channel);
         //get Proxy object
         FieldInfo proxyObjectFieldInfo =
            typeof(HttpClientChannel).GetField("_proxyObject",
                                               BindingFlags.Instance |
                                               BindingFlags.NonPublic);
         //set up proxy explicitly.
         proxyObjectFieldInfo.SetValue(clientChannel, proxy );
      }

      private bool StartTcpServer()
      {
         bool result = false;
         try
         {
            BinaryClientFormatterSinkProvider bcfs =
               new BinaryClientFormatterSinkProvider();
            BinaryServerFormatterSinkProvider bsfs =
               new BinaryServerFormatterSinkProvider();
            bsfs.TypeFilterLevel = TypeFilterLevel.Full;

            IDictionary id = new Hashtable();
            id = new Hashtable();
            id["port"] = 0;
            id["typeFilterLevel"] = TypeFilterLevel.Full;
            id["name"] = System.Guid.NewGuid().ToString();

            TcpChannel tcc = new TcpChannel(id, bcfs, bsfs);
            ChannelServices.RegisterChannel(tcc);
            this.im = (IMediator) Activator.GetObject(typeof(IMediator),
                                                      this.tcpServerUrl);
            result = true;

         }
         catch (RemotingException ex)
         {
            MessageBox.Show(ex.Message + " Stact trace: " +
                            ex.StackTrace);
         }
         finally
         {
         }
         return result;
      }

      private void btnConnect_Click(object sender, System.EventArgs e)
      {
         // StartHttpServer();
         if (txtUserName.Text.CompareTo(string.Empty) == 0)
         {
            MessageBox.Show("Please enter user name.");
         }
         else
         {
            StartTcpServer();

            if (this.im != null)
            {
               this.em = new EventsClass();
               this.em.UserName = this.txtUserName.Text;
               this.em.Message = "Hi!! I'm joining chat..";

               this.em.ClientListHandler +=
                  new GetClientsList(this.em_ClientListHandler);
               this.em.WelComeHandler +=
                  new WelComeMessage(this.em_WelComeHandler);
               this.em.GetMessageFromOthersHandler +=
                  new GetMessageFromOthers
                  (this.em_GetMessageFromOthersHandler);
               this.em.UserLeftHandler +=
                  new UserLeftChat(this.em_UserLeftHandler);
               try
               {   
                  this.im.ConnectToChat(em);
                  this.btnConnect.Enabled = false;
                  this.stsConnected.Text = em.UserName +
                     " successfully connected.";
                  this.Text = em.UserName;
                  this.grpSend.Enabled = true;
                  this.txtUserName.Enabled = false;
                  this.txtMessage.BackColor =  Color.LightCyan;
                  this.txtSendMessage.BackColor = Color.LightYellow;
                  this.grpClientChatBox.BackColor = Color.LightSkyBlue;
               }
               catch (RemotingException ex)
               {
                  this.lblErrorMessage.Text = ex.Message;
                  MessageBox.Show("Exception occured. " + ex.Message);
                  this.ReleaseHandlers();
               }
               catch (System.Net.Sockets.SocketException socEx)
               {
                  this.lblErrorMessage.Text = socEx.Message;
                  MessageBox.Show("Exception occured. " + socEx.Message);
                  this.ReleaseHandlers();
               }
               catch (Exception ex)
               {
                  this.lblErrorMessage.Text = ex.Message;
                  MessageBox.Show("Exception occured. " + ex.Message);
                  this.ReleaseHandlers();
               }
            }
         }
      }

      private void ReleaseHandlers()
      {
         try
         {
            this.em.ClientListHandler -=
               new GetClientsList(this.em_ClientListHandler);
            this.em.WelComeHandler -=
               new WelComeMessage(this.em_WelComeHandler);
            this.em.GetMessageFromOthersHandler -=
               new GetMessageFromOthers
               (this.em_GetMessageFromOthersHandler);
            this.em.UserLeftHandler -=
               new UserLeftChat(this.em_UserLeftHandler);
         }
         catch (Exception ex)
         {
            MessageBox.Show("No handlers to release. Error: " +
                            ex.Message);
         }
      }

      public void em_ClientListHandler(IClientImplement ici)
      {   
         this.clientList = ici.ClientList;
         Thread th = new Thread(new ThreadStart(this.GetClientList));
         th.Start();
      }

      private void GetClientList()
      {
         this.lstUsers.Items.Clear();
         foreach (IClientImplement icc in this.clientList)
         {
            this.lstUsers.Items.Add(icc.UserName);
         }
         this.lstUsers.BackColor = Color.LightBlue;
         this.lblUserCount.Text =
            "There are currently " + this.clientList.Count.ToString() +
            " users connected.";
      }

      public void em_WelComeHandler(IClientImplement ici)
      {
         this.iciClient = ici;
         Thread th = new Thread(new ThreadStart(this.NewUserJoined));
         th.Start();
      }

      private void NewUserJoined()
      {         
         this.txtMessage.AppendText(Environment.NewLine);
         this.txtMessage.AppendText(this.iciClient.UserName +
            " joined chat at: " + DateTime.Now.ToString());
      }

      private void btnSend_Click(object sender, System.EventArgs e)
      {
         Thread th = new Thread(new ThreadStart(this.SendMessage));
         th.Start();
      }

      private void SendMessage()
      {
         if (this.txtSendMessage.Text.CompareTo(string.Empty) != 0)
         {
            this.em.Message = txtSendMessage.Text.Trim();
            em.ReceiverName = "ALL";
            this.im.SendMessageToAll(em);
            this.txtSendMessage.Text = string.Empty;
         }
      }

      public void em_GetMessageFromOthersHandler(IClientImplement ici)
      {
         bool isAdded = false;
         this.iciClient = ici;
         Thread th =
            new Thread(new ThreadStart(this.GetMessageFromOtherClients));
         th.Start();
         IDictionaryEnumerator ide =
            this.hsPrivateWindows.GetEnumerator();
         while (ide.MoveNext())
         {
            if (ide.Key.ToString().CompareTo
               (this.iciClient.UserName) == 0)
            {
               isAdded = true;
            }
         }
         if (!isAdded)
         {         
            if (this.iciClient.ReceiverName.CompareTo
               (this.txtUserName.Text) == 0)
            {
               this.hsPrivateWindows.Add(this.iciClient.UserName, true);
               Thread th1 =
                  new Thread(new ThreadStart(this.OpenPrivateChatWindow));
               th1.Start();
            }
         }
      }

      private void OpenPrivateChatWindow()
      {
         PrivateChat pc = new PrivateChat();
         pc.Text = this.txtUserName.Text + " is chatting with " +
                   this.iciClient.UserName;
         pc.CallerName = this.iciClient.UserName;
         pc.MyName = this.txtUserName.Text;
         pc.UserLeft += new PrivateUserLeft(this.RemoveFromPrivateList);
         pc.ShowDialog();
      }

      private void GetMessageFromOtherClients()
      {         
//         if (this.iciClient.ReceiverName.CompareTo
//            (this.txtUserName.Text) == 0)
//         {
//            this.txtMessage.AppendText(Environment.NewLine);
//            this.txtMessage.AppendText("Private from " +
//               this.iciClient.UserName + " says: "
                                         + iciClient.Message);
//         }
//         else 
         if (this.iciClient.ReceiverName.CompareTo("ALL") == 0)
         {
            this.txtMessage.AppendText(Environment.NewLine);
            this.txtMessage.AppendText(this.iciClient.UserName +
               " says: " + iciClient.Message);
         }
      }

      private void Form1_Closing(object sender,
                                 System.ComponentModel.CancelEventArgs e)
      {
         try
         {
            this.ReleaseHandlers();
            this.im.RemoveMe(em);
         }
         catch (Exception ex)
         {
            MessageBox.Show("Server may be closed..." + ex.Message);
         }
      }

      private void Form1_Closed(object sender, System.EventArgs e)
      {
         this.ReleaseHandlers();
      }

      public void em_UserLeftHandler(IClientImplement ici)
      {
         this.iciClient = ici;
         Thread thLeft =
            new Thread(new ThreadStart(this.UserLeftChatRoom));
         thLeft.Start();
      }

      private void UserLeftChatRoom()
      {
         this.txtMessage.AppendText("\n" + this.iciClient.UserName +
                                    " left chat at: " +
                                     DateTime.Now.ToString());
      }

      private void txtSendMessage_KeyDown(object sender,
         System.Windows.Forms.KeyEventArgs e)
      {
         if (e.KeyValue == 13)
         {
            Thread th = new Thread(new ThreadStart(SendMessage));
            th.Start();
         }
      }

      private void lstUsers_DoubleClick(object sender,
                                        System.EventArgs e)
      {
         bool isAdded = false;
         IDictionaryEnumerator ide =
            this.hsPrivateWindows.GetEnumerator();

         while (ide.MoveNext())
         {
            if (ide.Key.ToString().CompareTo
               (this.iciClient.UserName) == 0)
            {
               isAdded = true;
            }
         }
         if (!isAdded)
         {
            Thread th = new Thread(new ThreadStart(this.BeginPrivateChat));
            th.Start();
         }
      }

      private void BeginPrivateChat()
      {
         this.hsPrivateWindows.Add(this.lstUsers.SelectedItem.
              ToString(), true);
         PrivateChat pc = new PrivateChat();
         pc.Text = this.txtUserName.Text + " is chatting with " +
                   this.lstUsers.SelectedItem.ToString();
         pc.CallerName = this.lstUsers.SelectedItem.ToString();
         pc.MyName = this.txtUserName.Text;
         pc.UserLeft += new PrivateUserLeft(this.RemoveFromPrivateList);
         pc.ShowDialog();
      }

      private void Form1_Load(object sender, System.EventArgs e)
      {
         SplashScreen ss = new SplashScreen();
         ss.Refresh();
         ss.ShowDialog();
      }

      public void RemoveFromPrivateList(string userName)
      {
         Hashtable hs = new Hashtable();
         IDictionaryEnumerator ide =
            this.hsPrivateWindows.GetEnumerator();
         while (ide.MoveNext())
         {
            string uName = Convert.ToString(ide.Key);
            if (uName.CompareTo(userName) == 0)
            {
               continue;
            }
            else
            {
               hs.Add(uName, true);
            }
         }
         this.hsPrivateWindows.Clear();
         ide = hs.GetEnumerator();
         while (ide.MoveNext())
         {
            this.hsPrivateWindows.Add(ide.Key, ide.Value);
         }         
      }
   }
/***************************************************************/

Remoting Chat Application

EventClass that is sent to the server as an object

/***************************************************************/
/// <summary>
   /// Summary description for EventsClass.
   /// </summary>
   /// 

   public delegate void GetClientsList(IClientImplement clientObject);
   public delegate void WelComeMessage(IClientImplement clientObject);
   public delegate void GetMessageFromOthers(IClientImplement
                                             clientObject);
   public delegate void UserLeftChat(IClientImplement clientObject);
   
   [Serializable]
   public class EventsClass : EventsManager
   {
      private string userName = string.Empty;
      private string msg = string.Empty;
      private ArrayList clientList = null;
      private string receiver = string.Empty;

      public event GetClientsList ClientListHandler;
      public event WelComeMessage WelComeHandler;
      public event GetMessageFromOthers GetMessageFromOthersHandler;
      public event UserLeftChat UserLeftHandler;

      public EventsClass()
      {
         //
         // TODO: Add constructor logic here
         //
      }

      public override System.Collections.ArrayList ClientList
      {
         get
         {
            return this.clientList;
         }
         set
         {
            this.clientList = value;
         }
      }

      public override string UserName
      {
         get
         {
            return this.userName;
         }
         set
         {
            this.userName = value;
         }
      }

      public override string Message
      {
         get
         {
            return this.msg;
         }
         set
         {
            this.msg = value;
         }
      }

      public override string ReceiverName
      {
         get
         {
            return this.receiver;
         }
         set
         {
            this.receiver = value;
         }
      }

      public override void SendMessageTome(IClientImplement
                                           clientObject)
      {
         if (this.GetMessageFromOthersHandler != null)
         {
            this.GetMessageFromOthersHandler(clientObject);
         }
      }

      public override void SendWelcomeMessageTome
         (IClientImplement clientObject)
      {
         if (this.ClientListHandler != null)
         {
            this.ClientListHandler(clientObject);
         }
         if (this.WelComeHandler != null)
         {
            this.WelComeHandler(clientObject);
         }
      }

      public override void UserLeft(IClientImplement clientObject)
      {
         if (this.ClientListHandler != null)
         {
            this.ClientListHandler(clientObject);
         }
         if (this.UserLeftHandler != null)
         {
            this.UserLeftHandler(clientObject);
         }
      }
   }

/***************************************************************/

Remoting Chat Application

When a user wants to begin a private chat with another user, a private chat window is automatically opened on the other user's side.

Private chat is a small winform that will send and receive messages from a single client. A hash table is maintained in ChatClient that contains a list of private windows. This will prevent the opening of a new private chat window for the same user. When the private chat window is closed, the hash table is updated.

/***************************************************************/
public delegate void PrivateUserLeft(string userName);
   /// <summary>
   /// Summary description for PrivateChat.
   /// </summary>
   ///    
   public class PrivateChat : System.Windows.Forms.Form
   {
      private System.Windows.Forms.GroupBox grpPrivateChat;
      private System.Windows.Forms.Label lblErrorMessage;
      private System.Windows.Forms.Button btnSend;
      private System.Windows.Forms.TextBox txtSendMessage;
      private System.Windows.Forms.TextBox txtMessage;
      /// <summary>
      /// Required designer variable.
      /// </summary>
      private System.ComponentModel.Container components = null;

      #region My Variables
      
      private string callerName = string.Empty;
      private string myName = string.Empty;
      private string message = string.Empty;
      private IMediator im;
      private EventsClass em;
      private IClientImplement iciClient;
      public event PrivateUserLeft UserLeft;
      private string httpServerUrl =
         ConfigurationSettings.AppSettings["HttpServerURL"].ToString();
      private string tcpServerUrl =
         ConfigurationSettings.AppSettings["TcpServerURL"].ToString();

      #endregion

      #region Public Properties
      
      public string CallerName
      {
         get
         {
            return this.callerName;
         }
         set
         {
            this.callerName = value;
         }
      }

      public string MyName
      {
         get
         {
            return this.myName;
         }
         set
         {
            this.myName = value;
         }
      }

      public string Message
      {
         get
         {
            return this.message;
         }
         set
         {
            this.message = value;
         }
      }

      #endregion

      public PrivateChat()
      {
         //
         // Required for Windows Form Designer support
         //
         InitializeComponent();

         //
         // TODO: Add any constructor code after
         // InitializeComponent call
         //
      }

      /// <summary>
      /// Clean up any resources being used.
      /// </summary>
      protected override void Dispose( bool disposing )
      {
         if( disposing )
         {
            if(components != null)
            {
               components.Dispose();
            }
         }
         base.Dispose( disposing );
      }

      #region Windows Form Designer generated code
      /// <summary>
      /// Required method for Designer support - do not modify
      /// the contents of this method with the code editor.
      /// </summary>
      private void InitializeComponent()
      {
         this.grpPrivateChat = new System.Windows.Forms.GroupBox();
         this.lblErrorMessage = new System.Windows.Forms.Label();
         this.btnSend = new System.Windows.Forms.Button();
         this.txtSendMessage = new System.Windows.Forms.TextBox();
         this.txtMessage = new System.Windows.Forms.TextBox();
         this.grpPrivateChat.SuspendLayout();
         this.SuspendLayout();
         // 
         // grpPrivateChat
         // 
         this.grpPrivateChat.Controls.Add(this.lblErrorMessage);
         this.grpPrivateChat.Controls.Add(this.btnSend);
         this.grpPrivateChat.Controls.Add(this.txtSendMessage);
         this.grpPrivateChat.Controls.Add(this.txtMessage);
         this.grpPrivateChat.Location = new System.Drawing.Point(16, 8);
         this.grpPrivateChat.Name = "grpPrivateChat";
         this.grpPrivateChat.Size = new System.Drawing.Size(384, 312);
         this.grpPrivateChat.TabIndex = 1;
         this.grpPrivateChat.TabStop = false;
         this.grpPrivateChat.Text = "groupBox1";
         // 
         // lblErrorMessage
         // 
         this.lblErrorMessage.ForeColor = System.Drawing.Color.Red;
         this.lblErrorMessage.Location =
            new System.Drawing.Point(16, 248);
         this.lblErrorMessage.Name = "lblErrorMessage";
         this.lblErrorMessage.Size = new System.Drawing.Size(352, 48);
         this.lblErrorMessage.TabIndex = 11;
         // 
         // btnSend
         // 
         this.btnSend.BackColor =
            System.Drawing.Color.FromArgb(((System.Byte)(128)),
                                         ((System.Byte)(128)),
                                         ((System.Byte)(255)));
         this.btnSend.Font =
            new System.Drawing.Font("Microsoft Sans Serif", 11F,
                                    System.Drawing.FontStyle.Bold,
                                    System.Drawing.GraphicsUnit.Point,
                                    ((System.Byte)(0)));
         this.btnSend.Location = new System.Drawing.Point(300, 184);
         this.btnSend.Name = "btnSend";
         this.btnSend.Size = new System.Drawing.Size(72, 48);
         this.btnSend.TabIndex = 10;
         this.btnSend.Text = "Send";
         this.btnSend.Click += new System.EventHandler(this.btnSend_Click);
         // 
         // txtSendMessage
         // 
         this.txtSendMessage.BackColor = System.Drawing.Color.MistyRose;
         this.txtSendMessage.ForeColor = System.Drawing.Color.Maroon;
         this.txtSendMessage.Location =
            new System.Drawing.Point(12, 184);
         this.txtSendMessage.Multiline = true;
         this.txtSendMessage.Name = "txtSendMessage";
         this.txtSendMessage.Size = new System.Drawing.Size(272, 48);
         this.txtSendMessage.TabIndex = 9;
         this.txtSendMessage.Text = "Hi!!";
         // 
         // txtMessage
         // 
         this.txtMessage.BackColor =
            System.Drawing.Color.FromArgb(((System.Byte)(255)),
                                          ((System.Byte)(224)),
                                          ((System.Byte)(192)));
         this.txtMessage.Font =
            new System.Drawing.Font("Microsoft Sans Serif", 9F,
                                    System.Drawing.FontStyle.Regular,
                                    System.Drawing.GraphicsUnit.Point,
                                    ((System.Byte)(0)));
         this.txtMessage.ForeColor = System.Drawing.Color.Blue;
         this.txtMessage.Location = new System.Drawing.Point(12, 32);
         this.txtMessage.Multiline = true;
         this.txtMessage.Name = "txtMessage";
         this.txtMessage.ReadOnly = true;
         this.txtMessage.Size = new System.Drawing.Size(360, 136);
         this.txtMessage.TabIndex = 8;
         this.txtMessage.Text = "
            /**********WELCOME TO PRIVATE CHAT ROOM ****************/";
         // 
         // PrivateChat
         // 
         this.AcceptButton = this.btnSend;
         this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
         this.BackColor =
            System.Drawing.Color.FromArgb(((System.Byte)(255)),
                                          ((System.Byte)(255)),
                                          ((System.Byte)(192)));
         this.ClientSize = new System.Drawing.Size(416, 333);
         this.Controls.Add(this.grpPrivateChat);
         this.Name = "PrivateChat";
         this.Text = "PrivateChat";
         this.Closing +=
            new System.ComponentModel.CancelEventHandler
            (this.PrivateChat_Closing);
         this.Load += new System.EventHandler(this.PrivateChat_Load);
         this.grpPrivateChat.ResumeLayout(false);
         this.ResumeLayout(false);
      }
      #endregion

      private bool StartTcpServer()
      {
         bool result = false;
         try
         {
            BinaryClientFormatterSinkProvider bcfs =
               new BinaryClientFormatterSinkProvider();
            BinaryServerFormatterSinkProvider bsfs =
               new BinaryServerFormatterSinkProvider();
            bsfs.TypeFilterLevel = TypeFilterLevel.Full;

            IDictionary id = new Hashtable();
            id = new Hashtable();
            id["port"] = 0;
            id["typeFilterLevel"] = TypeFilterLevel.Full;
            id["name"] = System.Guid.NewGuid().ToString();

            TcpChannel tcc = new TcpChannel(id, bcfs, bsfs);
            ChannelServices.RegisterChannel(tcc);
            this.im =
               (IMediator) Activator.GetObject(typeof(IMediator),
               this.tcpServerUrl);
            result = true;
         }
         catch (RemotingException ex)
         {
            MessageBox.Show(ex.Message + " Stact trace: " +
                            ex.StackTrace);
         }
         finally
         {
         }
         return result;
      }

      public void em_GetMessageFromOthersHandler(IClientImplement ici)
      {         
         this.iciClient = ici;
         if (this.iciClient.ReceiverName.CompareTo(this.myName) == 0 ||
            this.iciClient.UserName.CompareTo(this.myName) == 0)
         {
            Thread th =
               new Thread(new ThreadStart
                         (this.GetMessageFromOtherClients));
            th.Start();
         }
      }

      private void GetMessageFromOtherClients()
      {
         this.txtMessage.AppendText(Environment.NewLine);
         this.txtMessage.AppendText(this.iciClient.UserName + "
                                    says: " + iciClient.Message);
      }

      private void btnSend_Click(object sender, System.EventArgs e)
      {
         try
         {
            if (this.em == null)
            {
               this.StartTcpServer();
               this.em = new EventsClass();
               this.em.ReceiverName = this.callerName;
               this.em.UserName = this.myName;
               this.em.UserName = this.myName + "|" + this.callerName;
               this.em.ReceiverName = this.callerName;
               this.im.ConnectToPrivateChat(this.em);
               this.em.GetMessageFromOthersHandler +=
                  new GetMessageFromOthers
                  (this.em_GetMessageFromOthersHandler);
            }
            Thread th = new Thread(new ThreadStart(this.SendMessage));
            th.Start();
         }
         catch (Exception ex)
         {
            MessageBox.Show
               ("Exception occured in btnSend_Click. Error: " +
                ex.Message);
         }
      }
        
      private void SendMessage()
      {
         try
         {
            if (this.em == null)
            {
               throw new ApplicationException("Client object null.");
            }
            this.em.Message = this.txtSendMessage.Text;
            this.em.ReceiverName = this.callerName;
            this.em.UserName = this.myName + "|" + this.callerName;
            if (this.im == null)
            {
               throw new ApplicationException("Remote proxy not set.");
            }
            else
            {
               this.im.SendPrivateMessage(this.em);
               this.txtSendMessage.Text = string.Empty;
            }
         }
         catch (Exception ex)
         {
            MessageBox.Show("Error occured in SendMessage: Message: "
                            + ex.Message + " Statck trace: "
                            + ex.StackTrace);
         }
      }

      private void PrivateChat_Load(object sender, System.EventArgs e)
      {
         this.grpPrivateChat.Text =
            this.myName + " is privately chatting with "
                        + this.callerName;
         grpPrivateChat.BackColor = Color.LightSteelBlue;
      }      

      private void PrivateChat_Closing(object sender,
         System.ComponentModel.CancelEventArgs e)
      {
         if (UserLeft != null)
         {
            UserLeft(this.callerName);
         }
      }
   }
/***************************************************************/

Remoting Chat Application

Configure ChatClient

In the app.config file, change the server URL and test the application.

Problems faced

The application works very fine on Windows XP and Windows 2k, but gives following error when tried on Windows 2k3. It's because of some security issues.

Error

Server encountered an internal error.  For more information,
turn on customErrors in the server's .config file.

Server stack trace:

Exception rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage
   (IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke
   (MessageData& msgData, Int32 type)
at ChatMediator.IClientImplement.SendMessageTome
   (IClientImplement clientObject)
at RemoteServer.Mediator.SendMessageToAll(IClientImplement ici)
   in E:\Jayant\RemotingChatApplication\RemoteServer\Server.cs:line 73

About the Author

If you have run the application, you are already familiar with me. Still, I'll introduce my self. I'm Jayant D. Kulkarni, from Pune (one of the IT hubs in INDIA), Maharashtra, India. I'm working on .NET (C# 1.1, 2.0, ASP.NET 1.1, 2.0, VB.NET) for more than 1.5 years. I've total IT experience of nearly three years. Currently, I'm working with Mahindra-British Telecom, one of the leading telecom solution providers. I've BRAINBENCH certifications in C#, ASP.NET, ADO.NET, and .NET framework.

Please let me know your views, modifications you would like to see and suggestions at jdkulkarni@gmail.com.

Visit me at: http://jdkulkarni.tripod.com.



About the Author

Jayant Kulkarni

Dear Friends, I'm from Pune and curently working with Symantec Corp. I'm having more than 7 years of exp in software field and have worked on areas like ASP.NET, C#, .NET remoting, web services, pocket pc applciations. I'm a brainbench certified software engineer in .NET framework, C#, ADO.NET and ASP.NET. If you like any of my articles or you want to suggest some changes and improve the way I code, write articles feel free to mail me at: jayantdotnet@gmail.com

Downloads

Comments

  • There are no comments yet. Be the first to comment!

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: May 7, 2014 @ 1:00 p.m. ET / 10:00 a.m. PT This eSeminar will explore three popular games engines and how they empower developers to create exciting, graphically rich, and high-performance games for Android® on Intel® Architecture. Join us for a deep dive as experts describe the features, tools, and common challenges using Marmalade, App Game Kit, and Havok game engines, as well as a discussion of the pros and cons of each engine and how they fit into your development …

  • The exponential growth of data, along with virtualization, is bringing a disruptive level of complexity to your IT infrastructure. Having multiple point solutions for data protection is not the answer, as it adds to the chaos and impedes on your ability to deliver consistent SLAs. Read this white paper to learn how a more holistic view of the infrastructure can help you to unify the data protection schemas by properly evaluating your business needs in order to gain a thorough understanding of the applications …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds