如何设置TcpListener始终侦听和接受多个连接?

Keh*_*mme 30 c# networking 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();
    }
}
Run Code Online (Sandbox Code Playgroud)

从它的外观来看,它已经在运行时一直在聆听,但我仍然要求它指明我喜欢永远倾听和多连接支持.

我怎样才能修改它以便在接受多个连接的同时不断听?

Use*_*678 53

侦听传入连接的套接字通常称为侦听套接字.当侦听套接字确认传入连接时,创建通常称为子套接字的套接字,其有效地表示远程端点.

为了同时处理多个客户端连接,您需要为服务器将接收和处理数据的每个子套接字生成一个新线程.这样做将允许侦听套接字接受并处理多个连接,因为在您等待传入数据时,您正在侦听的线程将不再阻塞或等待.

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();
}
Run Code Online (Sandbox Code Playgroud)

  • @SHM不是2年后回复的人,但是为了让异步进程继续进行,某个时候必须建立一个线程,因此,有人必须假脱机线程.即使在另一台机器的电线上,也会打开一个线程来等待响应.我不明白你将如何建立一个异步过程(例如,任务仍然是线程). (2认同)

unk*_*656 5

我今天遇到了类似的问题,解决方法如下:

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
   }
}
Run Code Online (Sandbox Code Playgroud)

我的循环没有卡在等待连接上,它确实接受了多个连接。


编辑:以下代码片段是async使用任务而不是线程的等效项。请注意,代码包含 C#-8 结构。

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
}
Run Code Online (Sandbox Code Playgroud)