Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/322.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何设置TcpListener以始终侦听和接受多个连接?_C#_Networking_Tcplistener - Fatal编程技术网

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

C# 如何设置TcpListener以始终侦听和接受多个连接?,c#,networking,tcplistener,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,

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

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();
    }
}
publicstaticvoidmain()
{
尝试
{
IPAddress=IPAddress.Parse(“127.0.0.1”);
WriteLine(“正在启动TCP侦听器…”);
TcpListener侦听器=新的TcpListener(ipAddress,500);
listener.Start();
while(true)
{
WriteLine(“服务器正在侦听”+listener.LocalEndpoint);
Console.WriteLine(“等待连接…”);
Socket client=listener.AcceptSocket();
Console.WriteLine(“已接受连接”);
Console.WriteLine(“读取数据…”);
字节[]数据=新字节[100];
int size=client.Receive(数据);
Console.WriteLine(“接收数据:”);
对于(int i=0;i
正如您所见,它总是在工作时侦听,但我想指定我希望应用程序能够侦听并同时支持多个连接

我如何修改此选项,以便在接受多个连接的同时不断侦听

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

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

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

  • while(true)
    {
    Socket client=listener.AcceptSocket();
    Console.WriteLine(“已接受连接”);
    var childSocketThread=新线程(()=>
    {
    字节[]数据=新字节[100];
    int size=client.Receive(数据);
    Console.WriteLine(“接收数据:”);
    对于(int i=0;i
    我今天遇到了一个类似的问题,并这样解决了它:

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

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

    如何异步设置它(而不为每个客户端旋转新线程?)@mrdyprosium scalability显然。你说得很明显,所以也许我对这个话题的理解程度很低。。。但为什么异步比线程更具可伸缩性?@mrdyprosium因为为操作系统创建和管理线程的成本很高,因此为每个客户端旋转一个线程的成本很高。除此之外,您为每个客户机创建的线程将不做任何事情,大多数只是等待从客户机获取一些东西。@SHM不是2年后回复的那个人,但为了让异步进程继续进行,在某个时候必须建立一个线程,因此,必须有人假脱机一个线程。即使在另一台机器的电线上,也会打开一条线等待响应。我不明白您如何建立异步进程(例如,任务仍然是线程)。指定
    127.0.0.1
    是否将侦听套接字限制为仅在本地计算机上工作?公共网络上的设备能够访问此侦听套接字吗?为什么使用
    新字节[100]数组?这是从客户端发送的数据大小吗?@barteloma这是很久以前的事了,我不记得了,但它可能只是一个神奇的数字。一般来说,当我想管理来自外部的监听时,我也会使用此解决方案,并可能正确地停止它。我面临的唯一问题是,如果设置为高,使用sleep命令会产生太多的延迟,如果设置为低,则会消耗cpu。有什么办法可以解决这个问题吗?我相信最好的解决方案是结合使用async/await和“Task.Delay(…)”。当我可以访问我的计算机时,我将尝试进一步阐述。太好了,让我们看看它是如何工作的。我的另一个想法是继续使用AcceptCpcClient而不嵌套到睡眠等待循环中,并在另一个单独的线程中启动它,然后在想要完成侦听时强制终止它。然后它抛出一个必须处理的异常。丑陋,但在速度方面似乎是最有效的,只是想知道是否有类似但更好的解决方案。我更新了答案,使用“Task.Delay(…)”包含异步代码。使用任务的异步编程被认为是基于线程的代码构造的“继承者”。最好的方法是在while循环中等待listener.AcceptTcpClientAsync。如果希望能够从外部关闭侦听套接字,则只需使用取消令牌关闭套接字并捕获AcceptCpclientAsync()引发的套接字异常
    
    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
       }
    }
    
    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
    }