我正在开发一个游戏TCP服务器,我计划它应能承受多达500个连接。数据传输不断发生(角色的移动,攻击等)。
我开始使用 TCPListener 进行开发,但是我遇到了性能问题。 我使用等待 XXXSync 方法来接受客户端,接收数据和发送消息。
我创建了一个模拟玩家行为的程序。它允许只创建30-40个连接,这导致100%的CPU。为了测试我的服务器,我使用了两台机器:一台是玩家的模拟器,另一台是服务器。 这些 30-40个客户端在服务器上加载 CPU 10-20%并且非常多(在100%时)同时断开所有TCP客户端。
我一直在寻找有关优化TCPListener的信息,但没有找到。我已经看过人们写过他们拥有一个拥有1000多个连接的服务器的主题,这很有效。
我认为原因可能在于我的服务器的逻辑,但是分析工具显示CPU负载的主要部分是获取和发送数据(等待client.ReadAsync / client.WriteAsync)。 Picture 1 | Picture 2
我开始寻找可能的替代品并找到 SocketAsyncEventArgs 。在论坛上,人们写道,这种方法可以将生产力提高2倍。我找到了一些用C#编写的服务器的源代码,并从中获取了SocketAsyncEventArgs的实现。
这真的大大提高了10-15倍的生产力。对于30次模拟,现在只有0.5-2%。
我在SocketAsyncEventArgs重写了玩家的模拟器,这让我可以用20%的CPU创建100个模拟。
在70名玩家之后,服务器上CPU的负载增长了7-13%。 分析工具显示CPU的主要用途是发送消息。 出于某种原因,对我来说最有效的选择是BeginWrite。写入不合适,因为它会阻止流。 WriteAsync比较慢,或者我只是误用了它。 Picture 3 | Picture 4
我无法在c#上找到有关优化套接字的信息。到处都有人写道,即使在TCPListener上,它们也都很好,对我来说这简直难以忍受。
还有其他方法可以改善效果吗?
P.S。我在i7第七代的计算机上测试了服务器。