Как настроить TcpListener, чтобы всегда слушать и принимать несколько соединений?

Здесь мое приложение для сервера:

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

Как он выглядит, он уже всегда прослушивает во время работы, но я все еще прошу указать, что мне бы хотелось как всегда слушать, так и поддерживать несколько соединений.

Как я могу изменить это, чтобы постоянно слушать, а также принимать несколько соединений?

Ответы

Ответ 1

Сокет, на котором вы слушаете входящие соединения, обычно называется гнездом для прослушивания. Когда прослушивающий сокет подтверждает входящее соединение, создается сокет, обычно называемый дочерним сокетом, который эффективно представляет удаленную конечную точку.

Чтобы одновременно обрабатывать несколько клиентских подключений, вам нужно будет создать новый поток для каждого дочернего сокета, на котором сервер будет получать и обрабатывать данные. Это позволит прослушивающему сокету принимать и обрабатывать несколько соединений, поскольку поток, на котором вы слушаете, больше не будет блокировать или ждать, пока вы ждете входящих данных.

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

Ответ 2

У меня была аналогичная проблема сегодня, и я решил это следующим образом:

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

         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
   }
}

Мой цикл не застрял в ожидании подключения, и он принял несколько подключений.