Click here to Skip to main content
Click here to Skip to main content

A Chat Server/Client Solution for Local Networks

, 31 May 2011 CPOL
Rate this:
Please Sign up or sign in to vote.
A chat server/client solution for local networks, terminal server/terminal client environments

Introduction

Before talking about the code, there are a couple of things that I want to point out. One, this is my first article and I'm a little bit excited. Two, I'm dealing with software development for personal purposes in an amateur fashion. They are probably not the best-practices. But my purpose is to reflect my ideas, find solution to my problems. Three, I have been following CodeProject for the past 1 year and I have learnt lots of things here, as a result I cannot distinguish from whom I have learnt something. So, if you think that some of the ideas which are presented here are yours, please contact me so that I can refer it to you.

Now, let's talk about the project in brief. This is mainly a server-client chat application designed for network environment. I have modified it so that it can be run on a terminal server/terminal client environment. I mean users log on a terminal server with a remote desktop connection client (Microsoft remote desktop connection, hoblink, etc.). I chose to make the server a console application to track users easily (who logged on or off...). But there are better solutions that can be implemented for the server-side.

Background

There are many chat solutions available here on CodeProject and also on the internet. I have tried to implement them, but in one way or the other they all seem to be a little bit confusing. At last I managed to find a solution as a result of a lot of digging. The solution not only consists of server side and client side applications, but also a linked list solution to keep users' information on the server-side. In fact, the linked list solution can be the subject of another article by itself, but I don't have that much time, so I will try to explain that here in brief. I have tried to give plenty of comments in the code to guide the users.

Using the Code

The solution consists of five projects:

  • ServerApp
  • ServerClass
  • ClientApp
  • ClientClass
  • LinkedList

I made this separation for the sake of reusability.

ServerApp is a console application.

namespace ServerAppSpace        //Namespace for the Server Application
{
//IServerApp is the interface for the server application to implement...
//it will provide necessary methods to interact with the server
class MsgServer : MarshalByRefObject, IServerApp     
                                                                        
    {
        #region IServerApp implementation
        ...
        #endregion
        [STAThread] 
        public static void Main(string[] args) 
        {
           TcpChannel channel = new TcpChannel(9001); 
           ChannelServices.RegisterChannel(channel); 

           ServerClass remService = new ServerClass(); 
           ObjRef obj = RemotingServices.Marshal(remService,"TcpService");   

           // Create applications MainForm 
           MsgServer frmMain = new MsgServer();      
           
           // provide marshaled object with reference to Application 
           remService.theMainServer = ( IServerApp) frmMain;
           
           ...

           RemotingServices.Unmarshal(obj);
           RemotingServices.Disconnect(remService);
    }
}

ServerClass holds the necessary interfaces (IServerApp, IMyService) for the ServerApp and ServerClass. ClientApp is a Windows Form, and it implements IClientApp. ClientClass holds the necessary interfaces (IClientApp, IClientClass) for the ClientApp and ClientClass. LinkedList is a project consisting of a class named LinkedList. I have provided necessary comments in its coding. Please refer to it now.

In the Server textbox, enter the machine name on which the server is running. If the client and the server are running on the same machine, you can enter "localhost".

In the Username textbox, enter the username you want to use. The server checks the username. If the username is in use, it will request you to change the name.

Click Logon. If any of the above textboxes is empty, it will request you to fill the necessary textbox.

You can send the message in two ways:

  • One, click on the username to whom you wish to send the message. Type in the message in the messageEntryBox, press Enter or click on "Send Message".
  • Two, click the checkbox Global. You don't have to select a user. The message will be sent to all online users.

If the "Global" checkbox is not checked, no user will be selected from the user list, now if you try to send a message, a warning will be popped up asking you to select a user.

Well, I haven't made the user list multi-selectable. Multi messaging other than "Global send" is currently not implemented.

The titlebar of the dialog is a custom made titlebar. I have disabled the original Toolbar of the Windows Form. (To do this, enter the properties of the Windows Form, change the value of the ControlBox property to false and also delete the value of the Text property.) I have put a label and a button at the top of the form to act as a titlebar. I have also changed their anchor settings for keeping their size and position synchronized with the changes in the main window. I have added an event for the label to move the window as expected from the original titlebar. (Thanks to MinaFawzi's article Creating a non rectangular form using GDI+.

I have also set the anchor for all the controls, so when the main window is resized they arrange themselves in accordance with the new situation.

If you click the button "X", the client logs off the server and will be closed. If you click "Logoff", a message box pops up asking for your choice...to logoff without closing the window, to logoff and close the window and do nothing... A better message box can be arranged here, but I don't have that much time.

For further improvements, an icon can be placed in the system tray and the taskbar display can be disabled. I may implement this later on.

Points of Interest

During the early stages of the coding process, I first created a server and made the clients regularly check the server for updates. But it seemed to me a little bit silly. Then I searched for another approach. The correct approach should be "a client sends a message to someone, the server gets the message and forwards it to the concerned user"; but how? So I decided to design the client side like the server side (in fact registering a separate TCP channel for each client and creating the client side class object that can be called by the server for pushing the message to the client). The main design is the same for both the server and the client sides. Create a class object with new and then marshal it.

Client-side

 ClientClass remService = new ClientClass(); 
 ObjRef obj = RemotingServices.Marshal(remService,"TcpClient");

Server-side

  ServerClass remService = new ServerClass(); 
  ObjRef obj = RemotingServices.Marshal(remService,"TcpService");

(Well, I must confess that .NET really facilitates communication between remote applications. If we develop this project in C++ using COM, lots of things will be coded manually and longer time will be required.) But later-on, again a change is required. Because the program will run on a network terminal server, the clients will log onto the network server with a terminal client. In the first approach, all the clients have the same static port number. This causes no problem for individual clients running on different machines, but in the terminal server-terminal client approach this static port causes problems... To overcome this situation, I have found a solution: before registering a TCP channel, the client can ask the server to send the port number. After getting this port number, the client registers its TCP channel and on the server side the server keeps this information to find the appropriate clients later on. The server sends the unique TCP number to each registering client. As a result, multiple clients can be initiated on a single and/or multiple machine(s).

Also I'd like to point out a problem that hampered me a lot. When I first designed the client, it always hanged on when I pressed the logon button to logon to the server. I couldn't find a solution at first, but then I found this article from Ingo Rammer: Thinktecture. It helped me a lot.

I have tested this client-server solution in a network environment with multiple machines running on WinXP Professional SP2. (.NET Framework 1.1). Much more testing is required, but this is all for now.

I tested the solution on VS 2005 and Vista SP2.

Revision

Version 1.01

  • Fixed build error - The solution should build now.
  • Sending message to selected users (not all users, only the selected ones)

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Evren Daglioglu
Software Developer
Turkey Turkey
No Biography provided

Comments and Discussions

 
QuestionVote 5 For You PinmemberGun Gun Febrianza13-Oct-12 16:19 
GeneralMy vote of 5 PinmemberGun Gun Febrianza13-Oct-12 16:18 
GeneralMy vote of 5 PinmemberFilip D'haene31-May-11 21:59 
GeneralMy vote of 4 Pinmemberjayachanakya27-Oct-10 8:44 
Questionrequest Pinmemberamin mehdiabadi11-Nov-08 13:41 
GeneralChat Message Pinmembersmraj15039-Nov-08 19:40 
GeneralChat PinmemberRahul Babu14-Mar-07 0:44 
GeneralChat web application PinmemberMember #375692312-Mar-07 22:34 
Generalabout chat server/client PinmemberGenius376218-Nov-06 18:00 
GeneralRelay server Pinmembershyler8231-Aug-06 23:40 
Generalchat Application Pinmemberravicool27-Mar-06 23:54 
QuestionServer stops accepting clients Pinmembernulkoud26-Oct-05 21:48 
GeneralYour CHAT Server/Client PinmemberShahab Fatemi18-Oct-05 5:37 
GeneralA chat server/client solution for local networks Pinmembervenu999922-Jun-05 20:36 
GeneralJabber PinsussRobert Shady16-Jun-05 3:44 
GeneralRemoting PinprotectorMarc Clifton6-Jun-05 2:02 
GeneralRe: Remoting PinmemberEvren Daglioglu6-Jun-05 2:23 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.1411019.1 | Last Updated 31 May 2011
Article Copyright 2005 by Evren Daglioglu
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid