C# TcpListener - 客户端数量有限

C# TcpListener - client number limited

亲爱的 Stack Overflow 社区,

我目前正在用 C# 开发在线 TCG。服务器在我自己的机器上运行得很好(四核,八线程 Windows 7)。我可以毫无问题地连接 12 个客户端。但是当我在服务器上启动它时,客户端的最大数量就会受到机器上处理器内核数量的限制。我 运行 单核 Windows 2016 服务器上的代码无法连接多个客户端来开始游戏。然后我运行四核Windows2012服务器上的服务器只能连接四个客户端并启动两个游戏。在有人断开连接之前,任何其他客户端都将被完全忽略。然后新客户端被接受,服务器崩溃。

服务器是 MS Visual Studio 2015 Windows Forms Application with .NET Framework 4.0。 Windows 服务器机器有 .NET Framework 4.0,我自己的机器有 4.5 版。

我很乐意提供您可能需要的任何其他信息并回答您的所有问题。

C# 中的服务器代码:

public void Init()
{
    try {
        server = new TcpListener(IPAddress.Any, port);
        server.Start();
        serverRunning = true;
        server.BeginAcceptTcpClient(AcceptTcpClient, server);
        OutputTB.Text = "server has been started on port " + port.ToString();
    }
    catch (Exception e) {
        OutputTB.Text = "socket error: " + e.Message;
    }
}

private void AcceptTcpClient(IAsyncResult newClient)
{
    if (!serverRunning)
        return;
    server.BeginAcceptTcpClient(AcceptTcpClient, server);

    TcpListener listener = (TcpListener)newClient.AsyncState;
    ServerClient client = new ServerClient(listener.EndAcceptTcpClient(newClient));
    Send("SWHO", client);
    connectedClients.Add(client);
    Invoke((MethodInvoker)delegate {
        ClientListBox.Items.Add("Waiting for authentification...");
    });

    NetworkStream stream = client.tcp.GetStream();
    StreamReader reader = new StreamReader(stream, true);
    while (client.connected && serverRunning) {
        if (stream.DataAvailable) {
            string data = reader.ReadLine();
            if (data != null)
                OnIncomingData(client, data);
        }
    }
    Invoke((MethodInvoker)delegate {
        if (client.authenticated)
            ClientListBox.Items.Remove(client.playerName);
        else
            ClientListBox.Items.Remove("Waiting for authentification...");
    });
    Send("SDISC", client);
    waitingClients.Remove(client);
    connectedClients.Remove(client);
    client.tcp.Close();
}

private void OnIncomingData()
{
    //process client data
}

线程池耗尽了!非常感谢 itsme86 和 usr 提供的有用提示。现在代码如下所示:

private void AcceptTcpClient(IAsyncResult ar)
{
    server.BeginAcceptTcpClient(AcceptTcpClient, server);
    Task.Run(() => ListenToIncomingData(IAsyncResult ar);
}

有一件事我很好奇:异步调用不也是消耗一个线程吗?为什么有足够的资源来处理它但没有足够的资源来处理未完成的回调?