Click here to Skip to main content
12,296,162 members (62,721 online)
Click here to Skip to main content
Add your own
alternative version


597 bookmarked

TCP/IP Chat Application Using C#

, 30 Jan 2006 CPOL
Rate this:
Please Sign up or sign in to vote.
This is a LAN chat application with TCP/IP socket programming technology in C#. This application is a multi thread network application and works in a non-blocking way. Public and private chat is also implemented in this code.


The power of network programming in .NET platform cannot be denied. Socket programming is the core of network programming in Windows and Linux, and today the .NET platform implements it in a powerful way. In this article, we will see the basics of socket programming in C#. To be precise, I have created a command client and a command server, to communicate between a remote server and up to 200 clients and send the specified commands to them. As a sample application, I have created a chat client application that uses this command client/server to implement chat functions. Before I start explaining my application, let me give you a small introduction on network programming and sockets taken from the book 'C# network programming', written by Richard Blum.


In socket-based network programming, you don't directly access the network interface device to send and receive packets. Instead, an intermediary connector is created to handle the programming interface to the network. Assume that a socket is a connector that connects your application to a network interface of your computer. For sending and receiving data to and from the network you should call the socket's methods.

Socket programming in C#

The 'System.Net.Sockets' namespace contains the classes that provide the actual .NET interface to the low-level Winsock APIs. In network programming, apart from which programming language to use there are some common concepts like the IP address and port. IP address is a unique identifier of a computer on a network and port is like a gate through which applications communicate with each other. In brief, when we want to communicate with a remote computer or a device over the network, we should know its IP address. Then, we must open a gate (Port) to that IP and then send and receive the required data.

IP addresses in C#

One of the biggest advantages you will notice in the .NET network library is the way IP address/port pairs are handled. It is a fairly straightforward process that presents a welcome improvement over the old, confusing UNIX way. .NET defines two classes in the System.Net namespace to handle various types of IP address information:

  • IPAddress
  • IPEndPoint


An IPAddress object is used to represent a single IP address. This value is then used in various socket methods to represent the IP address. The default constructor for IPAddress is as follows:

public IPAddress(long address)

The default constructor takes a long value and converts it to an IPAddress value. In practice, the default is almost never used. Instead, several methods in the IPAddress class can be used to create and manipulate IP addresses. The Parse() method is often used to create IPAddress instances:

IPAddress newaddress = IPAddress.Parse("");


The .NET Framework uses the IPEndPoint object to represent a specific IP address/port combination. An IPEndPoint object is used when binding sockets to local addresses, or when connecting sockets to remote addresses.

Connection-oriented and connectionless sockets

The world of IP connectivity revolves around two types of communication: connection-oriented and connectionless. In a connection-oriented socket, the TCP protocol is used to establish a session (connection) between two IP address endpoints. There is a fair amount of overhead involved with establishing the connection, but once it is established, the data can be reliably transferred between the devices.

Connectionless sockets use the UDP protocol. Because of that no connection information is required to be sent between the network devices and it is often difficult to determine which device is acting as a "server", and which is acting as a "client". We will focus on the first type of socket programming in this article.

Using connection-oriented sockets

In the .NET Framework, you can create connection-oriented communications with remote hosts across a network. To create a connection-oriented socket, separate sequences of functions must be used for server programs and client programs:


You have four tasks to perform before a server can transfer data with a client connection:

  1. Create a socket.
  2. Bind the socket to a local IPEndPoint.
  3. Place the socket in listen mode.
  4. Accept an incoming connection on the socket.

Creating the server

The first step to constructing a TCP server is to create an instance of the Socket object. The other three functions necessary for successful server operations are then accomplished by using the methods of Socket object. The following C# code snippet includes these steps:

IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, 8000);
Socket newsock = Socket(AddressFamily.InterNetwork,
                   SocketType.Stream, ProtocolType.Tcp);
Socket client = newsock.Accept();

The Socket object created by the Accept() method can now be used to transmit data in either direction between the server and the remote client.


Now that you have a working TCP server, you can create a simple TCP client program to interact with it. There are only two steps required to connect a client program to a TCP server:

  1. Create a socket.
  2. Connect the socket to the remote server address.

Creating the client

As it was for the server program, the first step for creating the client program is to create a Socket object. The Socket object is used by the socket Connect() method to connect the socket to a remote host:

IPEndPoint ipep = 
    new IPEndPoint(Ipaddress.Parse(""), 8000);
Socket server = new Socket(AddressFamily.InterNetwork,
                  SocketType.Stream, ProtocolType.Tcp);

This example attempts to connect the socket to the server located at address is the IP address of the local host (current computer) and is a loopback IP for testing a network application without a network. Of course, you can also use hostnames along with the Dns.Resolve() method in a real network. (Dns is in System.Net namespace). Once the remote server TCP program accepts the connection request, the client program is ready to transmit data with the server using the standard Send() and Receive() methods.

Blocking problem of network applications

Sockets are in blocking mode by default. In this mode they will wait forever to complete their functions, holding up other functions within the application program until they are complete. Many programs can work quite competently in this mode, but for applications that work in the Windows programming environment, this can be a problem. There are some ways to solve this problem. The first thing that comes to a programmer's mind is multi threading. I chose this solution in my application too. This is a simple way when compared to asynchronous network programming or the old 'Non-Blocking sockets' way.

Our command client/server

After a brief introduction on network programming in C#, I should give you more details about our command client/server application here. Of course, I can't write a book on network programming in this little article. This is only an introduction to network programming. You can find many samples and tutorials on MSDN and CodeProject explaining this concept in detail.

About the command server

The server application is a console program. After starting, it will bind to the '' local IP and wait on the port 8000 by default for clients. You can pass the IP and the port of the server as the first and second command line parameters when starting the server, if you have a real network. For example: c:\> ConsoleServer 8960.

I used BackgroundWorker to implement multithreading in time consuming functions in the server and client. One of these actions includes the acceptance part of the server:

bwListener = new BackgroundWorker();
bwListener.DoWork += new DoWorkEventHandler(StartToListen);

private void StartToListen(object sender , DoWorkEventArgs e)
   this.listenerSocket = new Socket(AddressFamily.InterNetwork, 
                           SocketType.Stream, ProtocolType.Tcp);
               new IPEndPoint(this.serverIP , this.serverPort));
   while ( true )

I have a class named ClientManager. When the server is connected to a remote client it passes the communication socket to this class and adds this new ClientManager object to a list of current connected remote clients. Each ClientManager object in the list is responsible for communicating with its remote client. The ClientManager object announces the server with various events defined in this class when an action takes place between the remote client and the server. These events are:

public event CommandReceivedEventHandler CommandReceived;

Occurs when a command is received from a remote client.

public event CommandSentEventHandler CommandSent;

Occurs when a command had been sent to the remote client successfully.

public event CommandSendingFailedEventHandler CommandFailed;

Occurs when a command sending action fails. This is may be because of disconnection or sending exception.

public event DisconnectedEventHandler Disconnected;

Occurs when a client is disconnected from this server.

Sending and receiving data

Since we have a command client/server application we should have a command object to send and receive data. This is implemented in a 'Command' class. This class is the same in client and server. When the server wants to send a command to the client it builds a Command object and then sends it to the client and vice versa.

The command class is good for the user of this code. But in the network, we can't send and receive an object or a type. Everything should be converted to byte array. So, we should convert this object to a byte array part by part and send or receive it over the network in real Send and Receive functions inside our code. The following code shows the send command method. 'cmd' is the command that we want to send to the remote client:

byte [] buffer = new byte [4];
buffer = BitConverter.GetBytes((int)cmd.CommandType);
this.networkStream.Write(buffer , 0 , 4);

//Sender IP
byte [] senderIPBuffer = 
buffer = new byte [4];
buffer = BitConverter.GetBytes(senderIPBuffer.Length);
this.networkStream.Write(buffer , 0 , 4);
this.networkStream.Write(senderIPBuffer, 0, 
//Sender Name
byte [] senderNameBuffer = 
buffer = new byte [4];
buffer = BitConverter.GetBytes(senderNameBuffer.Length);
this.networkStream.Write(buffer , 0 , 4);
this.networkStream.Write(senderNameBuffer, 0, 
byte [] ipBuffer = 
buffer = new byte [4];
buffer = BitConverter.GetBytes(ipBuffer.Length);
this.networkStream.Write(buffer , 0 , 4);
this.networkStream.Write(ipBuffer , 0 , ipBuffer.Length);

//Meta Data.
if ( cmd.MetaData == null || cmd.MetaData == "" )
    cmd.MetaData = "\n";

byte [] metaBuffer = 
buffer = new byte [4];
buffer = BitConverter.GetBytes(metaBuffer.Length);
this.networkStream.Write(buffer , 0 , 4);
this.networkStream.Write(metaBuffer, 0, metaBuffer.Length);

The send and receive are bidirectional operations. For example, when we send 4 bytes to the client, the client should read the 4 bytes. We should repeat this operation until all the sent data is read. See the receive code of the client here:

while ( this.clientSocket.Connected )
    //Read the command's Type.
    byte [] buffer = new byte [4];
    int readBytes = this.networkStream.Read(buffer , 0 , 4);
    if ( readBytes == 0 )
    CommandType cmdType = 
         (CommandType)( BitConverter.ToInt32(buffer , 0) );
    //Read the command's sender ip size.
    buffer = new byte [4];
    readBytes = this.networkStream.Read(buffer , 0 , 4);
    if ( readBytes == 0 )
    int senderIPSize = BitConverter.ToInt32(buffer , 0);
    //Read the command's sender ip.
    buffer = new byte [senderIPSize];
    readBytes = 
        this.networkStream.Read(buffer , 0 , senderIPSize);
    if ( readBytes == 0 )
    IPAddress senderIP = IPAddress.Parse(
    //Read the command's sender name size.
    buffer = new byte [4];
    readBytes = this.networkStream.Read(buffer , 0 , 4);
    if ( readBytes == 0 )
    int senderNameSize = BitConverter.ToInt32(buffer , 0);
    //Read the command's sender name.
    buffer = new byte [senderNameSize];
    readBytes = this.networkStream.Read(buffer, 0, senderNameSize);
    if ( readBytes == 0 )
    string senderName = 
    //Read the command's target size.
    string cmdTarget = "";
    buffer = new byte [4];
    readBytes = this.networkStream.Read(buffer , 0 , 4);
    if ( readBytes == 0 )
    int ipSize = BitConverter.ToInt32(buffer , 0);
    //Read the command's target.
    buffer = new byte [ipSize];
    readBytes = this.networkStream.Read(buffer , 0 , ipSize);
    if ( readBytes == 0 )
    cmdTarget = System.Text.Encoding.ASCII.GetString(buffer);
    //Read the command's MetaData size.
    string cmdMetaData = "";
    buffer = new byte [4];
    readBytes = this.networkStream.Read(buffer , 0 , 4);
    if ( readBytes == 0 )
    int metaDataSize = BitConverter.ToInt32(buffer , 0);
    //Read the command's Meta data.
    buffer = new byte [metaDataSize];
    readBytes = this.networkStream.Read(buffer , 0 , metaDataSize);
    if ( readBytes == 0 )
    cmdMetaData = System.Text.Encoding.Unicode.GetString(buffer);
    Command cmd = new Command(cmdType, 
                        IPAddress.Parse(cmdTarget), cmdMetaData);
    cmd.SenderIP = senderIP;
    cmd.SenderName = senderName;
    this.OnCommandReceived(new CommandEventArgs(cmd));
    this.OnServerDisconnected(new ServerEventArgs(this.clientSocket));

About the command client

The command client is very similar to the server. Everything is in the 'CommandClient' class. Since our application is an event driven program this class also has some events to announce the user of the occurred actions. Here is a brief definition of these events:

public event CommandReceivedEventHandler CommandReceived;

Occurs when a command is received from a remote client.

public event CommandSentEventHandler CommandSent;

Occurs when a command has been sent to the remote server successfully.

public event CommandSendingFailedEventHandler CommandFailed;

Occurs when a command sending action fails. This is because of disconnection or sending exception.

public event ServerDisconnectedEventHandler ServerDisconnected;

Occurs when the client is disconnected.

public event DisconnectedEventHandler DisconnectedFromServer;

Occurs when this client is disconnected from the remote server.

public event ConnectingSuccessedEventHandler ConnectingSuccessed;

Occurs when this client is connected to the remote server successfully.

public event ConnectingFailedEventHandler ConnectingFailed;

Occurs when this client fails on connecting to the server.

public event NetworkDeadEventHandler NetworkDead;

Occurs when the network fails.

public event NetworkAlivedEventHandler NetworkAlived;

Occurs when the network starts to work.


In this application, you can find the following concepts of .NET programming:

  • Socket programming, server side and client side.
  • Working with resources at runtime.
  • Concurrency management in multi threaded environment.
  • Calling windows API functions within C# code.
  • Creating custom events and eventargs, and throwing events in a UI safe mode.
  • Creating custom exceptions and throwing them as and when needed.
  • Generating an HTML page at runtime dynamically.

And many other .NET programming concepts that I couldn't explain in detail here. The code is fully XML commented and very clear to understand. Please contact me if there is any ambiguous point or you need any help on my code.


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


About the Author

Software Developer (Senior)
Australia Australia
MCTS: ASP.NET Applications
MCTS: ADO.NET Applications
MCTS: Windows Forms Applications
MCTS: Windows Communication Foundation Applications
MCPD: Enterprise Application Developer

You may also be interested in...

Comments and Discussions

AnswerRe: help Pin
Cao Huan23-Aug-12 2:17
memberCao Huan23-Aug-12 2:17 
AnswerRe: help Pin
pophelix21-Jan-13 4:46
memberpophelix21-Jan-13 4:46 
GeneralRe: help Pin
GreyChen9-Jun-13 14:59
memberGreyChen9-Jun-13 14:59 
Questionfrom 2006, nolonger works. Pin
dragonalumni15-Mar-12 1:52
memberdragonalumni15-Mar-12 1:52 
QuestionMake it work Pin
hossain10014-Mar-12 5:36
memberhossain10014-Mar-12 5:36 
Generalhi Pin
rooja_5923-Jan-12 22:29
memberrooja_5923-Jan-12 22:29 
GeneralRe: hi Pin
javidahm15-Apr-12 5:27
memberjavidahm15-Apr-12 5:27 
QuestionAbove Code Doesnot work with ME. Pin
Member 451592917-Dec-11 3:28
memberMember 451592917-Dec-11 3:28 
AnswerRe: Above Code Doesnot work with ME. Pin
Spricer19-Dec-12 17:54
memberSpricer19-Dec-12 17:54 
QuestionCompiles & runs on c#2010 express, but server crashes Pin
Miwin Solutions25-Nov-11 8:26
memberMiwin Solutions25-Nov-11 8:26 
QuestionClient joined update in the public chat screen Pin
BaByAsHeZ18-Nov-11 20:00
memberBaByAsHeZ18-Nov-11 20:00 
Questionuse this project in one pc Pin
klkamesh1718-Nov-11 7:34
memberklkamesh1718-Nov-11 7:34 
QuestionEncryotion over chat Pin
MHDJAZ16-Nov-11 0:00
memberMHDJAZ16-Nov-11 0:00 
AnswerRe: Encryotion over chat Pin
GUANJIN9-Oct-12 15:37
memberGUANJIN9-Oct-12 15:37 
GeneralMy vote of 1 Pin
Sam358616-Oct-11 20:54
memberSam358616-Oct-11 20:54 
Questionthere is no way to work this apps on WAN Pin
mostafa.elsadany16-Sep-11 21:43
membermostafa.elsadany16-Sep-11 21:43 
AnswerRe: there is no way to work this apps on WAN Pin
Spricer19-Dec-12 17:50
memberSpricer19-Dec-12 17:50 
QuestionSlow connection! [modified] Pin
EricSmekens8-Jul-11 21:45
memberEricSmekens8-Jul-11 21:45 
QuestionPotential problem with Read Pin
BobJanova28-Jun-11 1:59
memberBobJanova28-Jun-11 1:59 
Question[My vote of 1] click the close button or just kill the client server said client still connected Pin
yoru amama22-Jun-11 9:52
memberyoru amama22-Jun-11 9:52 
AnswerRe: [My vote of 1] click the close button or just kill the client server said client still connected Pin
mercede9-Nov-11 22:42
membermercede9-Nov-11 22:42 
Questionthis code makes no sense, two separate client applications show be talking to each other ROFL ROFL NOT TE SAME CLIENT APP TALK TO ITSELF Pin
yoru amama20-Jun-11 16:02
memberyoru amama20-Jun-11 16:02 
AnswerRe: this code makes no sense, two separate client applications show be talking to each other ROFL ROFL NOT TE SAME CLIENT APP TALK TO ITSELF Pin
ting_hust22-Aug-11 15:16
memberting_hust22-Aug-11 15:16 
GeneralMy vote of 5 Pin
3hemo43-May-11 11:21
member3hemo43-May-11 11:21 
Generalhelp me pleasssssssse Pin
aroma_kt23-Apr-11 5:03
memberaroma_kt23-Apr-11 5:03 
GeneralGood stuff Pin
BoneSoft14-Apr-11 5:57
groupBoneSoft14-Apr-11 5:57 
Generalnice ! ! look for help Pin
my name is coder ! ! !29-Mar-11 3:00
membermy name is coder ! ! !29-Mar-11 3:00 
Questionلطفا كمكم كنيد Pin
nasim1120-Feb-11 23:18
membernasim1120-Feb-11 23:18 
GeneralMy vote of 5 Pin
farzadfr23-Jan-11 2:51
memberfarzadfr23-Jan-11 2:51 
QuestionProshot is not available. Pin
Harish Arumalla18-Jan-11 18:47
memberHarish Arumalla18-Jan-11 18:47 
GeneralMy vote of 5 Pin
Howard_CMI3-Jan-11 14:38
memberHoward_CMI3-Jan-11 14:38 
QuestionAsynchronous communication Pin
Dipak V Bava2-Jan-11 8:17
memberDipak V Bava2-Jan-11 8:17 
Generalthank! Pin
fidodido1822-Dec-10 3:48
memberfidodido1822-Dec-10 3:48 
GeneralMy vote of 5 Pin
Kevin Wenrick11-Dec-10 3:14
memberKevin Wenrick11-Dec-10 3:14 
Generalconnection Error Pin
Priya.gsgp1-Dec-10 21:53
memberPriya.gsgp1-Dec-10 21:53 
GeneralMy vote of 5 Pin
86012907717-Nov-10 10:25
member86012907717-Nov-10 10:25 
GeneralMy vote of 1 Pin
navanirose27-Oct-10 20:52
membernavanirose27-Oct-10 20:52 
GeneralVery Well Written Pin
mash123020-Oct-10 5:55
membermash123020-Oct-10 5:55 
Generala small problem Pin
vbvp9-Sep-10 11:13
membervbvp9-Sep-10 11:13 
Generalsame code but for Pin
abusharkas22-Aug-10 18:20
memberabusharkas22-Aug-10 18:20 
AnswerRe: same code but for Pin
thatraja28-Jan-12 5:33
mvpthatraja28-Jan-12 5:33 
GeneralMy vote of 5 Pin
tigerwang2023-Aug-10 0:49
membertigerwang2023-Aug-10 0:49 
GeneralGreat Project! 5++++ Stars! Pin
Dave Sheets9-Jul-10 14:10
memberDave Sheets9-Jul-10 14:10 
GeneralConnection problems Pin
zimmwarrior2-May-10 0:12
memberzimmwarrior2-May-10 0:12 
GeneralRe: Connection problems Pin
SERVODROID2-Aug-11 21:53
memberSERVODROID2-Aug-11 21:53 
GeneralThankyou, friend! Pin
e_legion16-Apr-10 9:30
membere_legion16-Apr-10 9:30 
GeneralThanks Pin
elinta9-Apr-10 19:37
memberelinta9-Apr-10 19:37 
GeneralThank you so much :) Pin
simal1027-Feb-10 13:21
membersimal1027-Feb-10 13:21 
Generalgetting error "Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host." Pin
MayurPanchal22-Feb-10 6:55
memberMayurPanchal22-Feb-10 6:55 
Generalproblem with demo Pin
iyerakshay117-Feb-10 4:46
memberiyerakshay117-Feb-10 4:46 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    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.160525.2 | Last Updated 31 Jan 2006
Article Copyright 2006 by ALLEXY
Everything else Copyright © CodeProject, 1999-2016
Layout: fixed | fluid