Beginners Guide to Networking in C#

shabbir's Avatar author of Beginners Guide to Networking in C#
This is an article on Beginners Guide to Networking in C# in C#.
Rated 5.00 By 1 users
Most of the advanced .NET applications that you develop need to communicate with other applications. For instance, for downloading or uploading data to some remote server, networking is required. In order to send or receive email via SMTP or to send and receive webpages via an HTTP protocols, some sort of networking is integrated into an application. The .NET framework contains System.Net.* namespaces which provide networking functionalities.

The networking types that are available in .NET framework deal mostly with the transport layer and the application layer of the OSI model. TCP and UDP are the basic transport protocols that are actually used for receiving and sending bytes of data. Application layer on the other hand deals with mostly advanced operations such as retrieving a particular web page using HTTP protocol, sending mails using SMTP protocol, transferring files using FTP protocol and converting domain names to IP addresses and vice versa via the DNS.

Addresses and Ports in C#



There are two types of addressing system followed by the internet in order to foster robust communication between applications: the IPV4 address and the IPV6 addresses. IPV4 is the most widely used scheme and IP address in this scheme is represented by 4 parts divided by a dot. For instance, 127.0.0.1 is an IPV4 address and refers to the host. .NET framework contains an IPAddress class in the System.Net namespace. This class can be used to store both IPV4 and IPV6 address. Our first example of this tutorial explains this concept.

Example1
Code:
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Net;

namespace CSharpTutorial
{ 
    class Program
    {
        public static void Main()
        {
            IPAddress ip1 = new IPAddress(new byte []{127,0,0,1});
            IPAddress ip2 = IPAddress.Parse("127.0.0.1");
            Console.WriteLine(ip1.Equals(ip2));
            Console.WriteLine(ip2.AddressFamily);

            Console.ReadLine();
        }
    }
}
In Example1, first of all, System.Net namespace has been imported since it contains the IPAddress class. Next in the Main method, an IPAddress object has been first instantiated using a constructor which takes a byte array where each byte represents a part of the address. Another way to instantiate IPAddress class is by calling static Parse method which takes a string as IP address.

In main method there are two IPAddress objects: p1 instantiated via constructor and p2, instantiated via static Parse method. Both contain similar IP address, this can be verified by calling Equals method on one of the two objects and passing the other as parameter. Next, we found address family of the IP address contained by p2 by calling its AddressFamily method. The output of the code in Example1 is as follows:

Output1



A single has a single IP address but it runs multiple network applications in parallel. This is possible because of Ports. The IP address is further broken down into ports so that multiple applications can run on a single IP address. There are 65535 ports that are referred by UDP and TCP protocols. Some ports are reserved for certain types of applications such as HTTP uses port 80 for communication. Similarly, FTP uses port 25 for network communication.
The combination of IP address and port in .NET framework is represented by the IPEndpoint class. Example2 explains the working of the IPEndPoint class.

Example2
Code:
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Net;

namespace CSharpTutorial
{ 
    class Program
    {
        public static void Main()
        {
            IPAddress ip1 = IPAddress.Parse("127.0.0.1");

            IPEndPoint ipport = new IPEndPoint(ip1, 4752);
            Console.WriteLine(ipport.ToString());

            Console.ReadLine();
        }
    }
}
The IPEndPoint class is instantiated via a constructor that takes two parameters. The first parameter is an IP address and the second parameter is the name of the Port. If IPEndPoint is printed by calling its ToString method, you will see that port is appended at the end of IP address, separated by colon. The output of the code in Example2 is as follows:

Output2



URIs in C#



URI stands for Unique Resource Identifier and is used to refer to a resource on the internet such as any webpage, a resource on LAN such as any file or to an email address. The .NET framework provides Uri class for referring to a URI. To get an idea of how Uri class works, have a look at the third example of this tutorial.

Example3
Code:
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Net;

namespace CSharpTutorial
{
    class Program
    {
        public static void Main()
        {
            string resource = @"http://www.myaddress.com:4444/myfile";
            string resource2 = @"http://www.myaddress2.com/myfile/index.html";

            Uri path = new Uri(resource);

            Uri path2 = new Uri(resource2);
            Console.WriteLine(path.Port);
            Console.WriteLine(path2.Port);

            Console.ReadLine();
        }
    }
}
In Example3, there are two strings. First string named, resource refers to some imaginary resource on the internet. Note that port has been explicitly mentioned in the resource string. The second string named resource2 also refers to some imaginary resource. Two Uri objects have been instantiated via constructors that take string resources to the resource on internet, LAN or an email address.

The path Uri object refers to resource and the path2 Uri object refers to resource2. Now if the Port property path is accessed, it would return 4444 since it has been explicitly mentioned in the resource string. However in resource2, port number has not been mentioned but of the Port property of the path2 object is accessed, it would return 80. This is due to the fact that the scheme of resource2 is http which runs on port 80 by default, therefore if port is not mentioned, default value of the port will be returned. The output of the code in Example3 is as follows:

Output3



Similarly, the absolute Uri, path and host can also be determined using the Uri object. Also, the IsLoopBack property can be used to check if the Uri refers to the local host. The Example4 of this article implement these concepts:

Example4
Code:
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Net;

namespace CSharpTutorial
{
    class Program
    {
        public static void Main()
        {
            string resource = @"http://www.myaddress.com:4444/myfile.txt";
            Uri path = new Uri(resource);

            Console.WriteLine("Absolute Uri : "+path.AbsoluteUri);
            Console.WriteLine("Absolute Path : " + path.AbsolutePath);
            Console.WriteLine("Host : " + path.Host);
            Console.WriteLine("Is loop back: " +  path.IsLoopback);
            Console.ReadLine();
        }
    }
}
In Example4, the AbsoluteUri property would return complete Uri. The AbsolutePath property would return only the path to the file on the Uri. The Host property would return the host name barring schema and the path attached to it. Finally, IsLoopBack property would check if the host is loop back which in this case would return false. The output of the code in Example4 is as follows:

Output4



Client Side Networking Classes



For client side network communication, WebRequest and WebResponce are two of the most widely used classes. These classes are used for managing HTTP, FTP and ‘file’ protocol. However a WebClient class is a more efficient way of request/response model. WebClient class performs activities of both WebRequest and the WebResponce classes, reducing the number of lines of code.

Another class new to the .NET framework 4.5 is the is the HttpClient which builds on the HttpWebRequest and HttpWebResonce classes. The HttpClient is used to request and response Http based services.

Though, both WebClient and HttpClient classes can be used to download and upload a file to a resource, WebClient is preferred since it offers progress reporting services that are not available with the HttpClient class. Example5 contains a basic demonstration of how WebClient class actually works. Have a look at it:

Example5
Code:
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Net;

namespace CSharpTutorial
{
    class Program
    {
        public static void Main()
        {
            WebClient client = new WebClient();
            client.Proxy = null;
            client.DownloadFile(@"http://imgs.g4estatic.com/c-sharp/networking/", @"Link.html");
            System.Diagnostics.Process.Start(@"Link.html");
          
            Console.ReadLine();
        }
    }
}
In Example5, a WebClient object named client has been instantiated via an empty constructor. The Proxy property of this WebClient object has been set to null since no proxy is being used to access the address.

Next comes the most important line of this Example. DownloadFile method has been called on the WebClient object client. The DownloadFile method takes two parameters: First is the address where file resides and second is the name of the file. This DownloadFile method in Example5 will download “Link.html” file from the address http://imgs.g4estatic.com/c-sharp/networking/. Now if you go and check the bin directory of your project, you will find Link.html file there.
In the next line of code, System.Diagnostics method has been used to open the file Link.html. This will be opened automatically in the default browser of the system.

In .NET framework 4.5 asynchronous versions of all the WebClient download methods have been introduced. For instance the DownloadFile method implemented in Example5 can be implemented asynchronously as:
Code:
wait client.DownloadFileTaskAsync(@"http://imgs.g4estatic.com/c-sharp/networking/", @"Link.html");
(For detail about asynchronous functions in C#, see this tutorial)

The progress of the download can also be tracked easily by handling the DownloadProgress changed event of the WebClient class. In the following the download progress of the file downloaded in Example5 has been shown. The condition has been attached using Task.Delay async method that if in 3 seconds, the other asynchronous methods are not completed or in other words, the download is not completed, cancel the download. The DownloadFile method would be called asynchronously, have a look at the 6th tutorial of this article:

Example6
Code:
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using System.Net;

namespace CSharpTutorial
{
    class Program
    {
        public static async void ProgressCheck()
        {
            WebClient client = new WebClient();
            client.Proxy = null;

            client.DownloadProgressChanged += (sender, args) =>
                Console.WriteLine(args.ProgressPercentage + "% download completed");
            Task.Delay(5000).ContinueWith(ant => client.CancelAsync());

            await client.DownloadFileTaskAsync(@"http://imgs.g4estatic.com/c-sharp/networking/", @"Link.html");
        }

        public static void Main()
        {

            ProgressCheck();
            Console.ReadLine();
        }
    }
}
The code in Example6 might look tricky to you in the beginning but it actually isn’t that difficult. A WebClient named client has been instantiated as in previous examples and its Proxy property is set to null.

In the next line, the DownloadProgress event of the WebClient’s client object has been hooked to the Console.WriteLine action where the ProgressPercentage property of the sender’s object would be displayed. This event would be called whenever the progress in the download is changed.

Then an asynchronous Task.Delay method has been implemented which completes is execution after three seconds. The ContinueWith statement has been hooked with the Task.Delay method which will execute when Task completes its execution. Inside the ContinueWith statement, a lambda expression has been passed which cancels all the parallel async tasks.

Finally, the DownloadProgress method has been called which asynchronously downloads the actual file from the given address. The output of the code in Example6 is as follows:

Output6



In the output, 100% is directly displayed since file was too small and by the time, Console.WriteLine action displayed the ProgressPercentage, it was already reached close to 100%. (The value has been rounded off it could be 99.991 % etc). The next 100 value is actually 100% and has been displayed when the download is completed.

This was a small file downloaded in Example6 was a small one and it only took milliseconds to download. However, if the file took time greater than 3 seconds, the Task.Delay method would have executed its ContinueWith statement and download would have been cancelled.

Writing an HTTP Server in C#



Till now, we have been studying individual characteristics and functionalities of the networking types in C#. In this section, we shall see that how actually things work together. We will write an HTTP Server which will listen to client requests and shall send appropriate response to the client. Our next example demonstrates that how an HttpListener class can be used to implement a basic HTTP server in C#. Have a look at the 7th example of this tutorial.

Example7
Code:
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using System.Net;
using System.Configuration;
using System.Text;

namespace CSharpTutorial
{
    class Program
    {
        public async static void Server()
        {
            HttpListener ls = new HttpListener();
            ls.Prefixes.Add("http://localhost:4562/MyFile/");
            ls.Start();

            HttpListenerContext listenercontext = await ls.GetContextAsync();

            string message = "The page you requested is: " + listenercontext.Request.RawUrl;

            listenercontext.Response.ContentLength64 = Encoding.UTF8.GetByteCount(message);
            listenercontext.Response.StatusCode = (int)HttpStatusCode.OK;

            using (Stream outstream = listenercontext.Response.OutputStream)
            using (StreamWriter swriter = new StreamWriter(outstream))
            await swriter.WriteAsync(message);
        }

        public static void Main()
        {
            Server();
            WebClient client =new  WebClient();
            string message = client.DownloadString("http://localhost:4562/MyFile/file.txt");
            Console.WriteLine(message);
            Console.ReadLine();
        }
    }
}
Several things are happening simultaneously in Example7. This is basically a basic HTTP server. First jump straight down to the Main method to see what is happening here. A server method has been called which actually starts the server. Now come back up to the Server method.

Inside the Server method, first of all the HttpListener object ls has been instantiated via HttpListener’s constructor. Next, the Uri on which this server will listen has been added via the Prefixes.Add method. Finally the HttpListener ls is started via the Start method.
The server has now started but It isn’t yet waiting for the requests from the client. The next line of code does this:
Code:
HttpListenerContext listenercontext = await ls.GetContextAsync();
At this point of time the Server method will not execute further unless a client makes a request on the Uri specified by the ls HttpServer object. Remember that the Main method and the Server method will run in parallel since Server method is asynchronous so. In the main method when the following line of code executes:
Code:
string message = client.DownloadString("http://localhost:4562/MyFile/file.txt");
When this line executes, a request is sent to the HTTP listener which is listening at the Uri specified by the DownloadingString method of the client object. At that address the HttpListener ls of the Server method is listening to requests. Therefore the code after the following line will start executing in the main method.
Code:
HttpListenerContext listenercontext = await ls.GetContextAsync();
The remaining lines of code are for formatting the response string that would be written asynchronously to the client. Now if the code in Example7 is executed, following output would be displayed

Output7



Actually what happens is that the listener receives request from the client and returns back the raw URL. In Example7, the client request was sent to:
http://localhost:4562/MyFile/file.txt

The listener receives this request and fetched raw URL from this method by calling this line of code:
Code:
string message = "The page you requested is: " + listenercontext.Request.RawUrl;
The raw URL is then appended at the end of the message sent by the server and then sent back to the client.

Using DNS (Domain Name Service) Classes



Every computer has an IP address through which it connects to a network. Websites and web services are deployed on physical machines and clients connect with these websites via the IP address of the system on which website is deployed. However, remembering complex IP addresses is not feasible.

There are millions and millions of websites and services and it is not possible for a human brain to remember all of them. For this reason easy and lucid website names are used to connect to a website. For instance when you want to connect to www.go4expert.com you do not have to specify the IP address. What actually happens in the background is that this name is converted automatically to the corresponding IP address and this is done by the Domain Name Service.

In the .NET Framework, System.Net namespace contains Dns class which can be used to perform conversion between an IP address to a domain name and from domain name back to IP address. In the next example of this article, Dns class has been used to perform such conversions. Have a look at the 8th example of this tutorial.

Example8
Code:
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using System.Net;
using System.Configuration;
using System.Text;
using System.Collections.Generic;

namespace CSharpTutorial
{
    class Program
    {
        public static void Main()
        {
            Console.WriteLine("Getting IP addresses from domain name ...");
            IPAddress [] ipaddresses =  Dns.GetHostAddresses("www.cricinfo.com");
            foreach (IPAddress ipaddress in ipaddresses)
            {
                Console.WriteLine(ipaddress.ToString());
            }

            Console.WriteLine("\n******************************\nGetting domain name from IP address ...");
            IPHostEntry domainnames = Dns.GetHostEntry("173.230.137.46");
            Console.WriteLine(domainnames.HostName);
       
            Console.ReadLine();
        }
    }
}
In Example8, inside the Main method we have called the GetHostAddress method of the static Dns class and passed it a domain name. Any domain name can be passed here. GetHostAddresses return all those IP addresses that are mapped to this domain name in the form of array of type IPAddress. We have stored the returned elements in ipaddresses array. Then a foreach loop has been used to enumerate through each IPAddress object in the ipaddresses array. The IP addresses are displayed on the console via ToString method.
Similarly, in order to convert an IP address to a domain name, static GetHostEntry method is called on the Dns class. This method returns the domain name that has been mapped to the IP address that has been passed to it as a parameter. The output of the code in Example8 is shown below:

Output8



It can be seen that two IP addresses have been returned by the GetHostAddresses method, this is due to the reason that the website’s domain has been mapped to these two IP’s. Some domain might be mapped to more than two IP addresses and some domain names might use a single IP address.

Dns class also contains asynchronous counter parts of the GetHostAddresses and GetHostEntry methods. They are implemented as follows:
Code:
IPAddress[] ipaddresses = await Dns.GetHostAddressesAsync("www.cricinfo.com");
IPHostEntry domainnames = await Dns.GetHostEntryAsync("173.230.137.46");
Domain names are implicitly converted to IP addresses and internally all the communication is made via IP addresses. Most of the networking name spaces internally resolve the domain names and then communicate to the IP addresses.

Networking is a very vast domain. You might not get all the terms used in this article. This is due to the fact that hardware side of any system is handled by network engineers which are specially trained for handling network related issues. However, a software developer must understand that how one can make use of networking types to connect to different network applications such as email clients, webservers and downloaders. In this article most of the basic networking concepts have been covered. However, this is just the tip of the iceberg, I would recommend you to further explore all the System.Net.* namespaces. Implement the types in your applications and see for yourself how they work. In case if you want to ask any question, ask them in comments.