C# 客户编号有限公司

C# 客户编号有限公司,c#,.net,server,tcplistener,C#,.net,Server,Tcplistener,亲爱的Stack Overflow社区: 我目前正在C#中开发一个在线TCG。服务器在我自己的机器上运行得非常好(四核,八线程Windows7)。我可以毫无问题地连接12个客户。但当我在服务器上启动它时,客户端的最大数量将受限于机器上处理器核心的数量。我在单核Windows 2016服务器上运行了该代码,无法连接多个客户端来启动游戏。然后我在四核Windows 2012服务器上运行服务器,只能连接四个客户端并启动两个游戏。任何其他客户都被完全忽略,直到有人断开连接。然后新客户端被接受,服务器崩溃

亲爱的Stack Overflow社区:

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

服务器是带有.NET Framework 4.0的MS Visual Studio 2015 Windows窗体应用程序。Windows Server机器有.NET Framework 4.0,我自己的机器有4.5版

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

C#中的服务器代码:


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

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

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

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

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

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

我会从AcceptTcpClient()中取出身份验证部分。也许在回调返回之前它无法释放线程。接受连接并离开那里。可能使用状态机或其他东西来指示您正在等待客户端进行身份验证,以便下次读取数据时,您知道如何处理它。您是否可以将此操作简化为仅接受连接的服务器,而不接受其他操作(以便它仍然重新启动)?这将简化问题。顺便说一句,你重新配置了你的线程池了吗?这闻起来有线程池耗尽的味道,这是不寻常的(也是一个bug)。也许在回调返回之前它无法释放线程。接受连接并离开那里。可能使用状态机或其他东西来指示您正在等待客户端进行身份验证,以便下次读取数据时,您知道如何处理它。您是否可以将此操作简化为仅接受连接的服务器,而不接受其他操作(以便它仍然重新启动)?这将简化问题。顺便说一句,你重新配置了你的线程池了吗?这闻到了线程池耗尽的味道,这是不寻常的(也是一个bug)。更重要的问题是:为什么线程用完了?通常情况下,运行时将它们生成成百个。异步IO根本不使用线程,但Task.Run不是异步IO。因此,这确实消耗了您以前使用的同一个池中的一个线程。它为什么现在起作用,这很神秘。应该还有一些工作需要完成。更神秘的是,旧版本在我的windows上工作。问题只发生在服务器上。它们是虚拟机。也许这就是问题所在?这些虚拟机的内核可能更少,导致可用线程更少。对我来说,这听起来像是您的进程中有人执行了ThreadPool.SetMaxThreads(Env.ProcessorCount)。有趣的是,仅当我停留在acceptClient()回调中时才应用该限制。现在,我让回调完成并在另一个函数中侦听,这个问题不再发生。更重要的问题是:为什么线程用完了?通常情况下,运行时将它们生成成百个。异步IO根本不使用线程,但Task.Run不是异步IO。因此,这确实消耗了您以前使用的同一个池中的一个线程。它为什么现在起作用,这很神秘。应该还有一些工作需要完成。更神秘的是,旧版本在我的windows上工作。问题只发生在服务器上。它们是虚拟机。也许这就是问题所在?这些虚拟机的内核可能更少,导致可用线程更少。对我来说,这听起来像是您的进程中有人执行了ThreadPool.SetMaxThreads(Env.ProcessorCount)。有趣的是,仅当我停留在acceptClient()回调中时才应用该限制。现在,我让回调完成并在另一个函数中侦听,这个问题不再发生。