【问题标题】:AcceptTcpClient and AcceptTcpClientAsync differenceAcceptTcpClient 和 AcceptTcpClientAsync 的区别
【发布时间】:2013-07-05 22:56:46
【问题描述】:

据我了解,这些行:

var client = await listener.AcceptTcpClientAsync();

var client = listener.AcceptTcpClient();

应该以同样的方式工作,但如果我尝试打开,例如,5k 连接(不关闭它们),很快监听器(异步)要么停止响应,要么抛出异常。

有人知道可能出了什么问题吗?

示例类:

class ListenerTest
{
    static int connectionNumber = 0;
    static int port = 23456;

    public void StartListening(bool async)
    {
        var listener = new TcpListener(IPAddress.Any, port);
        listener.Start();

        if (async)
        {
            var task = HandleConnectionsAsync(listener);
            task.Wait();
        }
        else
            HandleConnections(listener);
    }

    async Task HandleConnectionsAsync(TcpListener listener)
    {
        while (true)
        {
            Console.Write("Waiting for async connection...");
            var client = await listener.AcceptTcpClientAsync();
            Console.WriteLine("OK #" + connectionNumber);
            connectionNumber++;
        }
    }

    void HandleConnections(TcpListener listener)
    {
        while (true)
        {
            Console.Write("Waiting for sync connection...");
            var client = listener.AcceptTcpClient();
            Console.WriteLine("OK #" + connectionNumber);
            connectionNumber++;
        }
    }

    public static void ConnectTest(int count)
    {
        var ep = new IPEndPoint(IPAddress.Loopback, port);
        for (var i = 0; i < count; i++)
            new TcpClient().Connect(ep);
    }
}

用法:

static void Main(string[] args)
{
    var isAsync = true;
    ThreadPool.QueueUserWorkItem(new WaitCallback(StartListening), isAsync);
    ListenerTest.ConnectTest(5000);
}

static void StartListening(object state)
{
    var my = new ListenerTest();
    my.StartListening((bool)state);
}

【问题讨论】:

  • 否;其中之一是阻塞并浪费线程。
  • 异常说明了什么?
  • 尝试重现自己并查看 ;) 当在同一个程序实例中进行测试时,TcpListener 在接受大约 2500 个连接后抛出 SocketException “现有连接被远程主机强制关闭”。如果 TcpListener 和 TcpClients 在不同的程序实例中,那么 TcpListener 只是停止接受连接,没有任何异常,并且 TcpClient 在建立大约 120 个连接后抛出 SocketException "An existing connection was forced by the remote host"。

标签: c# asynchronous tcp async-await tcplistener


【解决方案1】:

一台机器不能有 100,000 个连接。 TCP/IP 只有16 bits for a port number (maximum 64k ports),其中很多是为操作系统或各种服务使用(或保留)的。

通常,only 16,383 of these ports are available 用于传入客户端连接,您需要与 all the other processes that use TCP/IP regularly 共享它们。

【讨论】:

  • 最初的问题是“为什么异步版本崩溃”,而不是关于 10 万个连接。您可以使用 10k 进行测试 - 异步仍然会崩溃。
【解决方案2】:

您的测试连接被 GC 杀死,如果您“固定”连接直到测试结束 - 您将获得 5000 个连接(我刚刚复制/粘贴并修复/测试了您的代码)。重写连接测试:

    public static void ConnectTest(int count)
    {
        var ep = new IPEndPoint(IPAddress.Loopback, port);
        List<TcpClient> clients = new List<TcpClient>();
        for (var i = 0; i < count; i++)
        {
            TcpClient cl = new TcpClient();
            clients.Add(cl);
            cl.Connect(ep);
        }
    }

另外请注意,在“现实世界”条件下,您需要在开始监听器循环之前添加类似这样的内容:

ThreadPool.SetMinThreads(100, 100);

这让您的代码在“突发”连接数/网络负载下工作。我们刚刚在 linux/mono 下成功“负载测试”了 7,5K 连接。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-07-14
    • 2011-10-20
    • 1970-01-01
    • 2019-05-11
    • 2013-08-07
    • 2011-10-20
    • 2020-01-23
    • 2021-12-02
    相关资源
    最近更新 更多