如何将 TcpListener 设置为始终侦听并接受多个连接

本文关键字:连接 TcpListener 设置 | 更新日期: 2023-09-27 18:35:40

这是我的服务器应用程序:

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

如您所见,它总是在工作时侦听,但我想指定我希望该应用程序能够侦听并同时支持多个连接。

我如何修改它以不断侦听,同时接受多个连接?

如何将 TcpListener 设置为始终侦听并接受多个连接

  1. 要侦听传入连接的套接字通常称为侦听套接字

  2. 侦听套接字确认传入连接时,将创建一个通常称为子套接字的套接字,该套接字有效地表示远程终结点。

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

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

我今天遇到了类似的问题,并像这样解决它:

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

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


编辑:以下代码片段是使用任务而不是线程的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
}

基本思想是,侦听器套接字始终侦听给定的IP和端口号。当有连接请求时,侦听器接受连接并使用 tcpclient 对象获取远程端点,直到连接关闭或丢失。