Friday, October 1, 2010

Data Exchange in the Internet and the Local Network over TCP / IP

To connect 2 computers in C# either over the internet or the local network, there are many ways.
The most of them will probably go over the use of sockets and of the TCP protocol. Today I want to show you one of them.
In the internet there are probably many good tutorials explaing this same topic in very detail.
In the general style of this blog I thus will just explain the code relatively shortly and leave the theory to others.
Still some sentences to that as introduction: To communicate in a network (like the internet), the connected computers need a common protocol they all understand. A such protocol is for example the here used TCP/IP protocol. This abbreviaton stands for Transmission Control Protocol / Internet Protocol and stands actually for a collection of many protocols for internet communication.
The TCP/IP protocol uses sockets for communication. These are endpoints between which the transmission takes palce, so one can view them as outer interfaces of the communication partners. Furtermore, the communication runs over a defined port. Ports are a method to sort the incoming data on a computer.
Every application, which sends and receives data over the internet or the local network, does so using a specific port. So the computer knows, where to forward the data to.

Okay, but now as promised to the praxis:
When wanting to connect multiple computers, one of them has to take the role of a server, to which multiple clients can connect to. In this example I will use 2 computers, between which data will be exchanged.
The server is represented by the class System.Net.Sockets.TcpListener, the client by System.Net.Sockets.TcpClient.
First the rudimentary code construction for the server:

  • Create a server object of the type TcpListener, set the port for the communication in the constructor.
  • Start the server with Start().
  • The function AcceptTcpClient() then waits until a client connects to the server and returns this TcpClient.
  • By the function GetStream() of the client then a stream can be created, with which data can be send and received.
  • Eventually, close the client via Close() and the server with Stop().

Now to the client:

  • Create a client object of the type TcpClient.
  • Connect via the function Connect() to the server, for that the ip address and the port has to passed as arguments.
  • By the function GetStream() of the client then a stream can be created, with which data can be send and received.

The data exchange is very simple in this example, the server runs in an infinite loop and waits for messages of the client.
The message polling can also be done with events for example, since a loop is not very resource saving.
The streams simply are created as instances of the basic class Stream, which sends and receives data as byte arrays.
The byte arrays are converted to strings with the help of the class ASCIIEnconding.
In the loop of the server first tries to read the next bytes of the stream via Read().
The function blocks the server until new data is available on the stream. So the loop is only that often iterated as messages are received.
If the client quits, the function does not block anymore, since 0 bytes are read, the loop is terminated.

In the following example the client logs on to the server, sends a message, waits 10 seconds, sends the same again and then quits.
Both programs, the client and the server, are realized as console applications and need the using directives:

using System.IO;
using System.Net.Sockets;

Now the source code

Server:

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

using System.IO;
using System.Net.Sockets;
using System.Net;

namespace TCPExample
{
    class TCPServer
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Starting server ...");

            TcpListener Server = new TcpListener(5550);
            Server.Start();
            Console.WriteLine("Server started.");
          
            Console.WriteLine("Waiting for connection ...");
            TcpClient Client = Server.AcceptTcpClient();
            Console.WriteLine("Connection established.");

            Stream MessageStream = Client.GetStream();

            while (true)
            {
                byte[] message = new byte[4096];
                int bytesRead;
                bytesRead = MessageStream.Read(message, 0, 4096);

                if (bytesRead == 0)
                {
                    // client has quit
                    break;
                }

                ASCIIEncoding encoder = new ASCIIEncoding();
                Console.WriteLine(encoder.GetString(message, 0, bytesRead));
            }

            // exit the program when client has quit
            Client.Close();
            Server.Stop();
        }
    }
}

Client:

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

using System.IO;
using System.Net.Sockets;

namespace TCPExample
{
    class TCPClient
    {
        static void Main(string[] args)
        {
            System.Net.IPAddress IP = System.Net.IPAddress.Parse("192.168.2.110");
            TcpClient Client = new TcpClient();
            Client.Connect(IP, 5550);
            Stream MessageStream = Client.GetStream();

            ASCIIEncoding encoder = new ASCIIEncoding();

            byte[] buffer = encoder.GetBytes("Hello Server!");

            MessageStream.Write(buffer, 0, buffer.Length);
            MessageStream.Flush();

            System.Threading.Thread.Sleep(10000);

            MessageStream.Write(buffer, 0, buffer.Length);
            MessageStream.Flush();

            Client.Close();
        }
    }
}


How different types of ip addresses are used in (in the local network and global in the internet), is explained in the next post.

No comments:

Post a Comment