How to set up TcpListener to always listen and accept multiple connections?

Basic idea is, there is listener socket always listening on a given IP and port number. When ever there is connection request, listener accept the connection and remote end point is taken with tcpclient object till connection is closed or lost.


I had a similar problem today, and solved it like this:

while (listen) // <--- boolean flag to exit loop
{
   if (listener.Pending())
   {
      Thread tmp_thread = new Thread(new ThreadStart(() =>
      {
         string msg = null;

         TcpClient clt = listener.AcceptTcpClient();

         using (NetworkStream ns = clt.GetStream())
         using (StreamReader sr = new StreamReader(ns))
         {
            msg = sr.ReadToEnd();
         }

         Console.WriteLine("Received new message (" + msg.Length + " bytes):\n" + msg);
      }
      tmp_thread.Start();
   }
   else
   {
       Thread.Sleep(100); //<--- timeout
   }
}

My loop did not get stuck on waiting for a connection and it did accept multiple connections.


EDIT: The following code snippet is the async-equivalent using Tasks instead of Threads. Please note that the code contains C#-8 constructs.

private static TcpListener listener = .....;
private static bool listen = true; // <--- boolean flag to exit loop


private static async Task HandleClient(TcpClient clt)
{
    using NetworkStream ns = clt.GetStream();
    using StreamReader sr = new StreamReader(ns);
    string msg = await sr.ReadToEndAsync();

    Console.WriteLine($"Received new message ({msg.Length} bytes):\n{msg}");
}

public static async void Main()
{
    while (listen)
        if (listener.Pending())
            await HandleClient(await listener.AcceptTcpClientAsync());
        else
            await Task.Delay(100); //<--- timeout
}

  1. The socket on which you want to listen for incoming connections is commonly referred to as the listening socket.

  2. When the listening socket acknowledges an incoming connection, a socket that commonly referred to as a child socket is created that effectively represents the remote endpoint.

  3. In order to handle multiple client connections simultaneously, you will need to spawn a new thread for each child socket on which the server will receive and handle data.
    Doing so will allow for the listening socket to accept and handle multiple connections as the thread on which you are listening will no longer be blocking or waiting while you wait for the incoming data.

while (true)
{
   Socket client = listener.AcceptSocket();
   Console.WriteLine("Connection accepted.");
    
   var childSocketThread = new Thread(() =>
   {
       byte[] data = new byte[100];
       int size = client.Receive(data);
       Console.WriteLine("Recieved data: ");
       
       for (int i = 0; i < size; i++)
       {
           Console.Write(Convert.ToChar(data[i]));
       }

       Console.WriteLine();
    
       client.Close();
    });

    childSocketThread.Start();
}