Question

This is my Server App:

public static void Main()
{
    try
    {
        IPAddress ipAddress = IPAddress.Parse("127.0.0.1");

        Console.WriteLine("Starting TCP listener...");

        TcpListener listener = new TcpListener(ipAddress, 500);

        listener.Start();

        while (true)
        {
            Console.WriteLine("Server is listening on " + listener.LocalEndpoint);

            Console.WriteLine("Waiting for a connection...");

            Socket client = listener.AcceptSocket();

            Console.WriteLine("Connection accepted.");

            Console.WriteLine("Reading data...");

            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();
        }

        listener.Stop();
    }
    catch (Exception e)
    {
        Console.WriteLine("Error: " + e.StackTrace);
        Console.ReadLine();
    }
}

As you can see , it always listens while working , but I would like to specify that I want the app be able to listen and to have multiple connections support in the same time.

How could I modify this to constantly listen while also accepting the multiple connections?

Was it helpful?

Solution

  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();
}

OTHER TIPS

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
}

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top