大家好,我是 Stack Overflow 的助手。
我有一个 .NET 的客户端-服务器应用程序,运行着几百个客户端。该项目是从 VB6 迁移到 .NET 大约一年前,并且是一款卡牌/棋盘游戏平台。
尽管下面我将尽可能提供详细信息,但问题在于当通道内有 40-70 个玩家时会出现频繁的卡顿。
架构
1. 服务器 (.NET 4.0)
- 分为三个项目:ServerNET、Listener 和 Channel。
- Listener 充当登录服务器,客户端首先连接到此服务器。它负责检查版本和帐户信息等内容。同时让客户端选择要连接的频道。它基本上是一个 TCPListener 在 do-while 中不断监听正在尝试连接的任何人。这不是导致双方冻结的原因。
- Channel 表示单个端口,客户端在完成 Listener 后连接到 Channels。就像航天飞机一样,这是主要部分。类似于 MIRC 频道,它将所有用户绑定在一起,大多数数据都被发送给频道内的人,例如聊天和可以加入其他玩家创建并由服务器托管的游戏。这是一个控制台应用程序,作为玩家的中心。玩家信息存储在“Client”类中,其中包括 TCPClient 和其他一些属性。每个客户端都运行在一个线程上,发出异步调用,由服务器处理。此外,“Client”对象存储在名为“ClientCollection”的集合类中。当频道内有大约 40-70 名玩家时,频道会被冻结。每个频道允许最多 100 名玩家。
- ServerNET 是整个系统相关的主体,并且执行所有其他通道无关的一般性任务。这是一个表单应用程序,运行服务器选项等内容。
2. 客户端 (.NET 2.0)
- 使用 TCPClient 运行,大多数情况下是单线程,而服务器则是多线程。
- 必须使用 .NET 2.0。
- 主要由视觉效果和其他不重要的内容组成。
当有 40 个以上的客户端连接到单个频道时,它开始随机完全冻结(或者说我们现在还没有证据或足够的数据来指出问题所在)。我们真的不认为网络流量是问题(还不确定),因为我们已经在不同的服务器上使用了各种设置进行了尝试。我们使用的所有服务器机器在硬件方面都能够处理那么多进程。因此,这是关于方法和代码方面发生了什么。
我们无法解决问题的原因在于我们不确定导致问题的原因。请看以下示例:系统A有55个人在线,他们的频道#1没有任何冻结。系统A使用A1 IP,频道位于16xxx端口。
系统B有25个人在线,他们的频道#4会随机冻结一两分钟。系统B使用B1 IP和18xxx频道端口。它与没有冻结的系统A在同一台机器上。
总之,这似乎与在线人数无关,但是当数字上升时,它发生得更频繁。
我们尝试在Channel项目中滚动Application.DoEvents()以进行无限循环,认为某些X进程会导致频道进入冻结状态几分钟,从而导致频道暂停。然后,在几秒钟内执行排队的每个操作,而它被冻结时。每个频道的CPU使用率平均在7%-20%之间,看起来情况正在好转。但是这并不是永久有效的解决方案。
我们怀疑以下事项:
- ClientCollection保存玩家和TCPClients是从CollectionBase继承的。也许这会在同步期间造成混乱。这曾经是一个数组,我们遇到了较少的这些问题。也许它不应该从CollectionBase继承,而应该从其他地方继承? - 我们使用SyncLock(C#中的锁)同步ClientCollection。(尽管我们在开始使用锁之前就有这个问题)
服务器信息 Intel Xeon X3460 2.80GHz 16 GB RAM 64位Windows Server 2008 Enterprise 我知道没有看到整个代码是不可能解决问题的,但我很遗憾无法发布代码。相反,我正在寻找一个思路来指导我。但是,我们很乐意分享任何其他信息以解决此问题。
感谢所有帮助!