我想做的是一个简单的 HTML5 聊天室,没什么特别的,一旦有人说了什么,它就会将它发送给当前连接到服务器的每个人,仅此而已。没有存储,没有什么复杂的。不过,它必须灵活,我的网站应该能够根据需要自动创建单独的聊天室。我看过很多演示和示例,但所有这些都要求我安装 node.js 或类似的需要终端访问的东西(我没有)。我目前正在其中一个免费的网站主机上运行,它为您提供了一个 ftp 客户端、一个 mysql 数据库、一些 php 支持,仅此而已。有没有办法做到这一点?或者也许我错过了什么,有没有办法在这类服务器上安装软件包?也许有人知道获得终端访问权限的方法?任何形式的帮助将不胜感激,谢谢。
5 回答
去过也做过。做对了并非易事。
我认为您必须做出一个重要决定:您是否希望聊天真的是即时的,或者是否可以延迟 2 秒,直到每个人都看到新消息。
如果延迟没问题,您实际上可以每 2 秒轮询一次服务器以查看是否有新消息可用。没有人喜欢延迟,但取决于你想做什么,它可能不是那么糟糕。然后,服务器将检查每个请求的数据库/文件并返回更新。这是一个非常简单的解决方案,并且有效。(如果您认为每 2 秒轮询一次会浪费资源并在服务器上造成不必要的负载……请继续阅读,替代方案可能会更糟。)
完全即时的聊天要求服务器可以立即向客户端发送新数据,而无需等待客户端请求。HTTP 本身并不支持这一点,如果您不想使用任何 Flash/Java,我知道的唯一方法是使用彗星请求。这些请求(通常是 AJAX)会故意在服务器上挂起一段时间,然后在需要发送到客户端的新数据可用或发生超时时准确返回。每次彗星请求返回时,客户端都会处理数据并立即发出另一个彗星请求,该请求将再次挂起,直到有新数据可用。我相信每个纯 HTML/JS 的聊天网站都是这样做的(Omegle、Facebook 等)。
现在,这是最容易的部分。但是如何在服务器上实现呢?让我们看一下这种情况:您在聊天中有 10 个用户,这意味着 10 个客户端每个都有一个等待新数据的悬空彗星请求。其中一位用户在聊天中写入了一些内容,这会导致向服务器发出附加请求以发布文本。您如何使服务器上的 PHP 脚本的这一次执行导致其他 10 次执行停止等待并返回新数据?(您可以用 Perl 或任何东西代替 PHP。)您将需要允许多个脚本执行相互通信的东西。(或者 PHP 代码本身可能每秒轮询一次数据库,但这又会引入延迟。)在那些脚本语言中,任何形式的进程间通信 (IPC) 都是困难的,尤其是你不这样做的时候。不知道 Web 服务器使用什么样的模型来执行它们。例如,Apache 可以为每个请求创建一个进程,或为每个请求创建一个线程,或者两者兼而有之。但也许你的主机使用 IIS 或其他东西,所以在这种情况下很难进行 IPC。我最终做的是在 PHP 中创建一个自己的服务器组件,它一直在运行,它的任务是在 PHP 脚本的不同执行之间传递消息。是的,这需要 shell 访问。所有 PHP 执行都将通过套接字连接到该服务器组件,并且可以传递消息。做对很棘手,但最后效果很好。或者别的什么,所以在这种情况下很难做IPC。我最终做的是在 PHP 中创建一个自己的服务器组件,它一直在运行,它的任务是在 PHP 脚本的不同执行之间传递消息。是的,这需要 shell 访问。所有 PHP 执行都将通过套接字连接到该服务器组件,并且可以传递消息。做对很棘手,但最后效果很好。或者别的什么,所以在这种情况下很难做IPC。我最终做的是在 PHP 中创建一个自己的服务器组件,它一直在运行,它的任务是在 PHP 脚本的不同执行之间传递消息。是的,这需要 shell 访问。所有 PHP 执行都将通过套接字连接到该服务器组件,并且可以传递消息。做对很棘手,但最后效果很好。
不幸的是,彗星请求可能非常浪费内存和 CPU 周期。我的 Apache 服务器有一个基于 PHP 的进程执行模型。因此,当聊天中有 100 人时,这意味着随时有 100 个待处理的彗星请求,这意味着有 100 个 Apache 进程在运行。即使一个新的 Apache 进程只使用 10MB,也就是总共 1GB!那是很多内存,而这些过程只不过是在等待某些事情发生。聊天是一个令人难以置信的记忆猪。此外,这样的聊天确实会产生很多请求:每次有人在聊天中说些什么,所有 100 个请求都会返回,然后您将立即收到 100 个新请求。聊天中的用户数量增加两倍通常意味着请求数量增加四倍。你真的希望这很活泼。阿帕奇不是 处理这个问题总是那么有效。周围有一些 Web 服务器软件专门针对彗星请求进行了调整,并且可以很好地扩展,但这再次需要比您拥有更多的服务器访问权限。
因此,为了完整起见,我的故事到此结束:与此同时,我放弃了所有 PHP 并完全重写了聊天。在我看来,Apache 和 PHP 非常不适合这种任务。现在有一个集成了高效的多线程 HTTP 服务器的 Java 服务器组件。我对它进行了压力测试,它的表现非常好:连接了 500 个垃圾邮件客户端,CPU 使用率不超过 15%,内存使用率保持在 150MB。这比我预期的要好得多。与 Apache/PHP 相比,它的响应能力也提高了很多。最终结果可以在http://www.dark-chat.info/查看,尽管由于各种原因聊天目前有些死。随着我有更多时间,这种情况有望改变。
好吧,我知道这对您没有多大帮助,因为您受到托管服务提供商的限制。如果没有 shell 访问权限,你能做的真的只有这么多。如果您可以延迟 2 秒(或延迟 1 秒)并且您不希望同时有超过 20 个用户,那么您真的可以进行轮询。有一些方法可以对此进行一些优化,例如,活跃用户可以获得 1 秒的投票,而那些很少写东西的用户可以获得 5 秒的投票。
也就是说,也许您也可以四处寻找某种托管解决方案。我确定您可以通过 iframe 嵌入聊天。
好的,这比我想要的要长得多。但我希望它可以帮助一些人。:)
我不能说太多,但目前用于此类事情的常用技术是彗星。
在 Comet 中,您打开一个对服务器的请求(例如,使用 AJAX 之类的东西),但您没有关闭它。您只需将其保持打开状态,但仅在需要时才将数据从服务器发送到客户端。这项技术还需要一些特殊的服务器,但我认为如果你谷歌一下,你肯定会找到一种用 PHP 实现 Comet 的方法(但我认为 Python 更适合这样的事情)......
希望这能给您一些想法,如何解决您的问题:)
在不使用任何插件(Flash、Java、...)的情况下实现聊天的唯一方法是WebSocket。(以特定间隔连接服务器以检查新消息是一种实现方式,但我认为它太“脏”了......)但是,我认为 Web 托管站点可能不提供 WebSocket 服务器。我建议您通过使用 Java/Flash 进行连接来制作 IRC 客户端。如果要使用 HTML/JS 制作 UI,请使用ExternalInterface
Flash 或JSObject
Java 中的插件和 JS 进行通信。
正如许多人所提到的,实现这一点的流行方法是使用 ajax、comet(或其他一些长轮询机制)或 WebSockets。
我的建议是使用 WebSockets,但正如前面提到的,您的主机可能不允许您设置套接字服务器。
如果您遇到这种情况,我建议使用Server Sent Events,这是另一种被 WebSockets 所掩盖的 HTML5 解决方案。
它将允许您向浏览器发送事件,并且仍然可以轻松地在 PHP 中实现。
HTML 5 有一个很酷的新特性,叫做 Web Sockets,它允许客户端和服务器之间真正的双向通信。但是,您不会找到任何便宜的共享托管计划来让您托管自己的 Web Socket 服务器。
您可以通过“老式”方式来伪造双向通信:使用 AJAX。基本上,客户端 JavaScript 每隔几秒就会向数据库发出一次请求,以检查是否有任何新的聊天消息要显示。发布新消息只是将该消息发布到服务器。
Comet 只是一种花哨的(更有效的,服务器端的)方式来做到这一点。