Socket Programming in C#...
In such a mode of communication, the server application listens to a specific port to receive data from the clients. In doing so, the server application is blocked (for other client requests) unless it receives data from the client application. On the other hand, while operating in the asynchronous mode, the server can process multiple client requests at the same point of time. Note that the asynchronous operations using sockets are typically used for long running tasks. Typical examples of such tasks are opening large files, reading or querying a database with large volumes of data, connecting to a remote computer, accessing resources remotely for long running operations, etc. Further, note that the asynchronous operations actually operate on a separate thread. Typically, applications have two types of threads, application thread and worker thread. An application thread is the main thread of the application; the worker thread is the thread that works in the background to perform asynchronous operations.
Note that the Socket class in the System.Net.Sockets namespace contains both synchronous and asynchronous methods. As an example, while the Connect() and Receive() methods are meant for synchronous operation, the BeginConnect() and EndConnect() methods as well as the BeginReceive() and EndReceive() methods are their asynchronous counterparts.
The System.Net namespace class contains an important class called Dns that can be used to access DNS (Domain Naming Service). Well, what is a DNS, anyway? Domain Naming Service or DNS is a naming service that is used to name the nodes over a network for simplicity reasons. The domain name is actually a textual name that identifies a host in a network. The DNS servers have the DNS names stored along with their corresponding IP addresses. The Wikipedia states, "The Domain Name system (DNS) associates various sorts of information with so-called domain names; most importantly, it serves as the "phone book" for the Internet by translating human-readable computer hostnames, e.g. www.example.com, into the IP addresses, e.g. 208.77.188.166, that networking equipment needs to deliver information. It also stores other information such as the list of mail exchange servers that accept email for a given domain. In providing a worldwide keyword-based redirection service, the Domain Name System is an essential component of contemporary Internet use." Now, in order to retrieve the host name of your local system, use the following:
Listing 1
Console.WriteLine("The host name of the local computer is: " + Dns.GetHostName());
The host name of the local computer is displayed as shown in the figure below.
Figure 1
using System; using System.Text; using System.Net; using System.Net.Sockets; namespace TestSocket { class Program { static void Main(string[]args) { try { IPHostEntry IPHost = Dns.GetHostEntry("www.hotmail.com"); IPAddress[]ipAddress = IPHost.AddressList; StringBuilder strIpAddress = new StringBuilder(); for (int i = 0; i < ipAddress.Length; i++) { strIpAddress.Append(ipAddress[i].ToString()); } Console.WriteLine("The IP Address is: " + strIpAddress.ToString()); } catch (SocketException ex) { Console.WriteLine("Error Occured! " + ex); } Console.Read(); } } }
When you execute the above program, the IP address of www.hotmail.com. In this case it displayed as 211.206.123.219. However, if you are not connected to the network, the method fails and a SocketException is thrown. The exception is caught in the catch block shown in the above program. The figures below illustrate the output in each case.
Figure 2
In this section we will discuss how to implement a simple client-server application using Sockets in C#. There will be two distinct applications, i.e., a Server application and a Client application. The Server application will connect to a port and be in the listen mode waiting for a Client to connect. Once the Client is connected, it will send a test message to the Server application using a StreamWriter. This text message will then be displayed in the Server application's console. Here is the source code of the Server application.
Listing 3: The SocketServer classusing System; using System.Text; using System.Net; using System.Net.Sockets; class SocketServer { public static void Main() { StreamWriter streamWriter; StreamReader streamReader; NetworkStream networkStream; TcpListener tcpListener = new TcpListener(5555); tcpListener.Start(); Console.WriteLine("The Server has started on port 5555"); Socket serverSocket = tcpListener.AcceptSocket(); try { if (serverSocket.Connected) { while (true) { Console.WriteLine("Client connected"); networkStream = new NetworkStream(serverSocket); streamWriter = new StreamWriter(networkStream); streamReader = new StreamReader(networkStream); Console.WriteLine(streamReader.ReadLine()); } } if (serverSocket.Connected) serverSocket.Close(); Console.Read(); } catch (SocketException ex) { Console.WriteLine(ex); } } }
Refer to the code snippet given above. The Server application starts the port 5555; displays a relevant message and waits for the incoming requests from the Client to connect to it. Now, when you run this application, the message "The Server has started on port 5555" will be displayed on the Server application's console. As soon as a Client gets connected to the same port, the message "Client connected" is displayed on the console. Here is the output when you execute this application.
Figure 4: The SocketServer console when started
Next, we will take a look at the source code of the Client application that will connect to the Server application using the same port, i.e., 5555. Here is the code.
Listing 4: The SocketClient classusing System; using System.Text; using System.Net; using System.Net.Sockets; class SocketClient { static void Main(string[]args) { TcpClient tcpClient; NetworkStream networkStream; StreamReader streamReader; StreamWriter streamWriter; try { tcpClient = new TcpClient("localhost", 5555); networkStream = tcpClient.GetStream(); streamReader = new StreamReader(networkStream); streamWriter = new StreamWriter(networkStream); streamWriter.WriteLine("Message from the Client..."); streamWriter.Flush(); } catch (SocketException ex) { Console.WriteLine(ex); } Console.Read(); } }
When you execute the Client application, here is how the output will look like at the Server application’s console.
Figure 5: The SocketServer console when the client is connected
Note that the message "Client connected" and the text sent by the client, "Message from the Client…", is displayed at the Server application’s console.