Joydip Kanjilal
Contributor

How to implement an asynchronous socket in C#

how-to
Jun 09, 20164 mins
C#Development Libraries and FrameworksMicrosoft .NET

You can increase the performance and scalability of your client-server applications by using asynchronous sockets. Here’s how.

abstract connection lines dots plotted points network vector
Credit: af_studio / Getty Images

A socket is defined as the endpoint of a two-way communication between two processes running over a network. Inter-process communication can be achieved using sockets. After a connection between the server and client, i.e., after the server process and the client process are established, they can communicate for the purpose of exchanging data using sockets.

Why do we need asynchronous sockets?

Asynchronous programming enables you to execute tasks without the need to pause the execution flow or responsiveness of your application. This in turn helps to improve the performance and responsiveness of your application. You can also build synchronous sockets, but such sockets don’t scale well since they block your thread. Asynchrony can perform resource-intensive I/O operations without the need to block the main or the executing thread of your application.

Create an asynchronous TCP socket in C#

To implement a TCP client-server socket communication, you would typically need to create a server process that should start at a particular port and also a client process that can start on any port and send a connection request to the server. The server process listens for incoming connection requests at the port on which it has been started.

The following code snippet illustrates how you can create a TCP socket and start it at a particular port.

IPHostEntry ipHostEntry = Dns.Resolve(Dns.GetHostName());
IPAddress ipAddress = ipHostEntry.AddressList[0];
IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, 8888);
TcpListener serverSocket = new TcpListener(ipEndPoint);
serverSocket.Start();

Let’s now create a class named ServerSocket that represents the asynchronous server socket class. This class would wrap the logic to create and start a TCP socket and also wait for incoming client connections.

public class SocketServer
   {
       private static TcpListener serverSocket;
       public async void StartServer()
       {
           IPHostEntry ipHostEntry = Dns.Resolve(Dns.GetHostName());
           IPAddress ipAddress = ipHostEntry.AddressList[0];
           IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, 8888);
           while (true)
           {
               serverSocket = new TcpListener(ipEndPoint);
               serverSocket.Start();
               Console.WriteLine("Server Socket started...waiting for connections...");
               try
               {
                   var tcpClient = await serverSocket.AcceptTcpClientAsync();
                   HandleConnectionAsync(tcpClient);
               }
               catch (Exception ex)
               {
                   Console.WriteLine(ex.ToString());
               }
           }
       }
   }

The HandleConnectionAsync will be used to process the individual clients.

private async void HandleConnectionAsync(TcpClient tcpClient)
       {
           //Write code here to process the incoming client connections
       }

Let’s now modify the code of the StartServer method to eliminate the looping. We can use an async model in lieu of looping for greater efficiency and improved performance.

public class SocketServer
{
  private static TcpListener serverSocket;
  public static void StartServer()
       {
           IPHostEntry ipHostEntry = Dns.Resolve(Dns.GetHostName());
           IPAddress ipAddress = ipHostEntry.AddressList[0];
           IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, 8888);
           serverSocket = new TcpListener(ipEndPoint);
           serverSocket.Start();
           Console.WriteLine("Asynchonous server socket is listening at: " + ipEndPoint.Address.ToString());
           WaitForClients();
       }
}

Refer to the ServerSocket class shown above. The static method StartServer of the ServerSocket class contains the necessary code to create a socket and start it. It also waits for incoming client connections sans the need of looping. Note the call to the WaitForClients method in the last statement of the StartServer method. The WaitForClients() method is shown below.

private static void WaitForClients()
       {
           serverSocket.BeginAcceptTcpClient(new System.AsyncCallback(OnClientConnected), null);
       }

The BeginAcceptTcpClient method has been used to asynchronously accept client connections. It should be noted that the BeginAcceptTcpClient operation must be completed by invoking the EndAcceptTcpClient method on the socket instance.

The OnClientConnected callback method is shown below.

       private static void OnClientConnected(IAsyncResult asyncResult)
       {
           try
           {
               TcpClient clientSocket = serverSocket.EndAcceptTcpClient(asyncResult);
               if (clientSocket != null)
               Console.WriteLine("Received connection request from: " + clientSocket.Client.RemoteEndPoint.ToString());
               HandleClientRequest(clientSocket);
           }
           catch
           {
               throw;
           }
           WaitForClients();
       }

Here is the signature of the HandleClientRequest method that does the actual processing of incoming client requests.

       private static void HandleClientRequest(TcpClient clientSocket)
       {
           //Write your code here to process the data
       }

And the following code snippet shows how you can start the server socket.

static void Main(string[] args)
       {
           SocketServer.StartServer();
           Console.Read();
       }

Create an asynchronous TCP client socket in C#

At the client side, you will need to run a client socket that connects to the server socket and sends and receives data to and from the server. The following class named IDGSocketClient represents our asynchronous client socket.

public class IDGSocketClient
   {
       System.Net.Sockets.TcpClient clientSocket = new System.Net.Sockets.TcpClient();
       NetworkStream networkStream;
       public void Connect(string ipAddress, int port)
       {
           clientSocket.Connect(ipAddress, port);
       }
        public void Send(string data)
       {
           //Write code here to send data
       }
       public void Close()
       {
           clientSocket.Close();
       }
       public string Receive()
       {
           //Write code here to receive data from the server
       }
   }

The following code snippet illustrates how you can connect to the server socket from the client and send data.

static void Main(string[] args)
       {
           IDGSocketClient client = new IDGSocketClient();
           client.Connect("127.0.0.1",8888);
           client.Send("Hello");
           Console.Read();
       }

The end.

Joydip Kanjilal
Contributor

Joydip Kanjilal is a Microsoft Most Valuable Professional (MVP) in ASP.NET, as well as a speaker and the author of several books and articles. He received the prestigious MVP award for 2007, 2008, 2009, 2010, 2011, and 2012.

He has more than 20 years of experience in IT, with more than 16 years in Microsoft .Net and related technologies. He has been selected as MSDN Featured Developer of the Fortnight (MSDN) and as Community Credit Winner several times.

He is the author of eight books and more than 500 articles. Many of his articles have been featured at Microsoft’s Official Site on ASP.Net.

He was a speaker at the Spark IT 2010 event and at the Dr. Dobb’s Conference 2014 in Bangalore. He has also worked as a judge for the Jolt Awards at Dr. Dobb's Journal. He is a regular speaker at the SSWUG Virtual Conference, which is held twice each year.

More from this author