web-dev-qa-db-ja.com

常に複数の接続をリッスンして受け入れるように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();
    }
}

見た目からは、すでに実行中は常にリッスンしていますが、常にリッスンし、複数の接続をサポートするように指定するように求めています。

複数の接続を受け入れながら、常にリッスンするようにこれを変更するにはどうすればよいですか?

29
Kehlan Krumme

着信接続をリッスンするソケットは、一般的にlistening socketと呼ばれます。リスニングソケットが着信接続を確認すると、一般的に子ソケットと呼ばれるソケットが作成され、リモートエンドポイントを効果的に表します。

複数のクライアント接続を同時に処理するには、サーバーがデータを受信して​​処理する子ソケットごとに新しいスレッドを生成する必要があります。そうすることで、リスニングソケットが複数の接続を受け入れて処理できるようになります。リスニングしているスレッドは、着信データを待機している間、ブロックまたは待機しなくなります。

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

今日も同様の問題があり、次のように解決しました。

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

私のループは、接続を待つことでスタックすることはなく、複数の接続を受け入れました。

1
unknown6656