In this series we are going to be looking at TCP IP, Client / Servers and what a massive world of opportunities this knowledge opens up to us, from Chat and Video Conferencing, to Invisible process communication, and even Service Management. But today let’s get the framework done.
The sample is built in Visual Studio 2012 Ultimate as an x86 targeted application using .Net Framework 4. We will be using NuGet packages, a number of 3rd party libraries. All of which will be fully explained to you ensuring that the final compilation of your App will be hassle free. Oh! And the sample code is verbosely commented so you should have no problem in working out what the code does.
Communication is fundamental to us all. But it is also fundamental to many programs. When your application connects with a database it has to communicate, when your browser connects to a website, it communicates and the vast majority of the communication that occurs on the internet is does through TCP communication. In this first example we will write a client and an “echo server” which simply replies with the message you sent – pretty much like the ping command. It doesn’t sound like much but it is the basis that we will start from.

Open Visual Studio 2012 and Create a New Project. Call the Project ClientApp. Now Click on the ClientApp Project in Solution Explorer and Add a New Project Called ServerApp. This makes it nice a simple for us to separate the Client and Server logic and code.
1. Change the form Text to Server and Client accordingly.
2. The Server is a little more complicated than the Client so we will design that first
· Add a StatusStrip to the Server Form
o Add two Labels to the StatusStrip and Set their Text Properties to
§ Number of Connections
§ 0
o Change the Second Labels Name to lblNumberOfConnections
· Add a RichTextBox to the Form and Set it’s Docking property to Fill
· Name The RichTextBox rtbServer
· Add a RichTextBox to the Form and Set it’s Docking property to Fill
· Name The RichTextBox rtbClient
Ok now we have created our front ends, you can format the RichTextBoxes any way you like. We need to start our coding. Again we will start with the Server.
Our server does three things
· It waits until a client connects
this.tcpListener = new TcpListener(IPAddress.Loopback, 3000); // Change to IPAddress.Any for internet wide Communication
this.listenThread = new Thread(new ThreadStart(ListenForClients));
this.listenThread.Start();
this.tcpListener = new TcpListener(IPAddress.Loopback, 3000); // Change to IPAddress.Any for internet wide Communication this.listenThread = new Thread(new ThreadStart(ListenForClients)); this.listenThread.Start();
· It Handles the client’s connection and communication
private void ListenForClients()
{
this.tcpListener.Start();
while (true) // Never ends until the Server is closed.
{
//blocks until a client has connected to the server
TcpClient client = this.tcpListener.AcceptTcpClient();
//create a thread to handle communication
//with connected client
connectedClients++; // Increment the number of clients that have communicated with us.
lblNumberOfConnections.Text = connectedClients.ToString();
Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
clientThread.Start(client);
}
}
private void ListenForClients() { this.tcpListener.Start(); while (true) // Never ends until the Server is closed. { //blocks until a client has connected to the server TcpClient client = this.tcpListener.AcceptTcpClient(); //create a thread to handle communication //with connected client connectedClients++; // Increment the number of clients that have communicated with us. lblNumberOfConnections.Text = connectedClients.ToString(); Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm)); clientThread.Start(client); } }
· It replies with the same message that it received (Echoes)
private void HandleClientComm(object client)
{
TcpClient tcpClient = (TcpClient)client;
NetworkStream clientStream = tcpClient.GetStream();
byte[] message = new byte[4096];
int bytesRead;
while (true)
{
bytesRead = 0;
try
{
//blocks until a client sends a message
bytesRead = clientStream.Read(message, 0, 4096);
}
catch
{
//a socket error has occured
break;
}
if (bytesRead == 0)
{
//the client has disconnected from the server
connectedClients--;
lblNumberOfConnections.Text = connectedClients.ToString();
break;
}
//message has successfully been received
ASCIIEncoding encoder = new ASCIIEncoding();
// Convert the Bytes received to a string and display it on the Server Screen
string msg = encoder.GetString(message, 0, bytesRead);
WriteMessage(msg);
// Now Echo the message back
Echo(msg, encoder, clientStream);
}
tcpClient.Close();
}
private void HandleClientComm(object client) { TcpClient tcpClient = (TcpClient)client; NetworkStream clientStream = tcpClient.GetStream(); byte[] message = new byte[4096]; int bytesRead; while (true) { bytesRead = 0; try { //blocks until a client sends a message bytesRead = clientStream.Read(message, 0, 4096); } catch { //a socket error has occured break; } if (bytesRead == 0) { //the client has disconnected from the server connectedClients--; lblNumberOfConnections.Text = connectedClients.ToString(); break; } //message has successfully been received ASCIIEncoding encoder = new ASCIIEncoding(); // Convert the Bytes received to a string and display it on the Server Screen string msg = encoder.GetString(message, 0, bytesRead); WriteMessage(msg); // Now Echo the message back Echo(msg, encoder, clientStream); } tcpClient.Close(); }
Our Client does three things
· It connects to the Server
client.Connect(serverEndPoint);
client.Connect(serverEndPoint);
· It sends a message
NetworkStream clientStream = client.GetStream();
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] buffer = encoder.GetBytes(msg);
clientStream.Write(buffer, 0, buffer.Length);
clientStream.Flush();
// Receive the TcpServer.response.
// Buffer to store the response bytes.
Byte[] data = new Byte[256];
NetworkStream clientStream = client.GetStream(); ASCIIEncoding encoder = new ASCIIEncoding(); byte[] buffer = encoder.GetBytes(msg); clientStream.Write(buffer, 0, buffer.Length); clientStream.Flush(); // Receive the TcpServer.response. // Buffer to store the response bytes. Byte[] data = new Byte[256];
· It displays the response
// String to store the response ASCII representation.
String responseData = String.Empty;
// Read the first batch of the TcpServer response bytes.
Int32 bytes = clientStream.Read(data, 0, data.Length);
responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);
rtbClient.AppendText(Environment.NewLine + "From Server: " + responseData);
// String to store the response ASCII representation. String responseData = String.Empty; // Read the first batch of the TcpServer response bytes. Int32 bytes = clientStream.Read(data, 0, data.Length); responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes); rtbClient.AppendText(Environment.NewLine + "From Server: " + responseData);
· Source code ClientApp:Form1.cs – The main interface to our Client application
· Source code ServerApp:Form1.cs – The main interface to our Server application
In the next of this series we shall start making things interesting!
To convert the solution to a previous version of Visual Studio you can use this free application: http://vsprojectconverter.codeplex.com/ or download and use Visual Studio 2013 Express which is freely available from Microsoft from here: http://www.visualstudio.com/downloads/download-visual-studio-vs.