AcceptTcpClient和AcceptTcpClientAsync的区别

时间:2013-07-08 14:43:46

标签: c# asynchronous tcp async-await tcplistener

根据我的理解,这些界限:

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

2 个答案:

答案 0 :(得分:4)

您的测试连接被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连接。

答案 1 :(得分: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共享它们。