5

是否有可能知道整个服务器上有多少个 PHP 类的实例对象(对于所有用户,而不仅仅是一个线程)。

这就是我想这样做的原因。我正在制作纸牌游戏,并且我想要拥有 Room 类(具有唯一的房间名称、玩家目前在房间内在线、已注册的 id ......)所以当一些用户加入服务器以获得新的活动房间列表时。当一个房间被取消(摧毁)时,我会向所有用户发送该信息(基本上是实时房间状态)。


好的,这就是我想要这样做的原因。我正在制作纸牌游戏项目,我想拥有 Room 类(具有唯一的房间名称,玩家目前在房间里在线,socked id ......)所以当一些用户加入服务器以获得新的活动房间列表时。当一个房间被取消(销毁)时,我会向所有用户发送该信息(基本上是实时房间状态)。我希望你明白我想做什么。

4

3 回答 3

4

你想实现一个多用户游戏,所以你应该为它使用客户端-服务器架构:设置一个在你的机器上运行并跟踪游戏状态的单一的、持久的服务器进程。每个用户请求都由一个 PHP“客户端”脚本处理,该脚本与游戏服务器对话并询问所有必要的信息。

这样,所有Room对象和所有玩家状态都存在于一个进程中:服务器。网络服务器(不要与您的游戏服务器混淆)启动客户端线程,它们以您想要的任何方式与游戏服务器异步对话。

如果您的情况非常简单,您也许可以将服务器进程替换为存储游戏当前状态快照的集中式数据库(包括活动房间和相关玩家的完整列表)。每个用户请求从数据库加载游戏状态,并写出任何更改。但我认为长期运行的服务器是更简单的方法。

编辑:您的问题表明对 PHP 的工作方式有些困惑。服务器为处理用户请求而启动的 PHP 线程非常短暂。假设您有 5 名玩家已经玩了一个小时。每隔几分钟或几秒钟,玩家就会向您的网络服务器发送一个请求。服务器启动一个处理请求并退出的 PHP 线程。游戏可能会持续几个小时,但大多数时候没有正在运行的线程,也没有类的实例可以计算。在任何时候,你都会有一些没有活跃连接的玩家。所以你需要某种持久的实体来在请求之间保持他们的游戏状态,你不妨让它独一无二。

编辑2:由于您似乎有点过头了,也许您应该选择第二个选项:忘记进程间通信并将游戏状态保存在数据库中:

每个 php 请求都是一个玩家操作。当用户单击一个按钮或其他任何东西时,您的 php 脚本会从数据库中加载它为游戏当前状态建模所需的所有信息。它会进行任何必要的清理工作(停用所有很久以前停止玩游戏的用户),然后处理用户的操作,保存对数据库的任何更改,并为用户生成一个新页面。然后它退出。这一切只需要一小部分时间。然后下一个用户(或同一个用户)提交另一个动作,你重新开始。

并发呢?除非您设法获得大量用户并且您的脚本真的很慢,否则不会有任何用户:您一次只能运行一个脚本副本。如果要禁止并发执行,请使用数据库事务来确保一次处理一个用户操作。如果这还不够,请了解客户端-服务器架构、进程间通信以及客户端-服务器解决方案所需的所有其他内容。

于 2013-03-01T20:42:34.507 回答
2

这绝对是一种粗略的方法,但您只需在类的构造函数中添加一些内容。这可能是记录一些东西、发送电子邮件、读取计数器和增量等......

显然,如果您想知道在任何给定时间点有多少实例,您还需要在析构函数中添加一些东西......

在阅读了您的答案(这应该是对您的原始问题的评论)之后,实现这一点的最佳方法是使用类方法和属性,这样任何实例都可以读取/更改共享计数。您仍然可以使用构造函数和析构函数来增加/减少活动表的计数等...,但该类将保持一个计数,所有实例都可以访问。

于 2013-03-01T20:20:37.873 回答
0

最简洁的答案是不。非常冗长而令人费解的答案是肯定的,但它需要大量的黑客攻击,或者编辑 php 源代码或使用 gdb(或类似的东西)来检查正在运行的内存。据我所知,绝对没有开箱即用的支持。

更好的问题是你为什么需要这个?您很可能试图解决一个更容易以另一种方式解决的问题。

您可能能够仅在对象实例化和销毁上使用 APC 增量和减量而侥幸,但如果这些对象真的太多以至于您需要对它们进行计数,那么您肯定会导致很大的性能问题。

于 2013-03-01T20:20:20.300 回答