在PHP中进行跨平台实时数据流的最佳方法是什么?

7
我一直在想如何使用PHP进行“真正”的(半)实时数据流传输。
可能的应用包括:聊天室,拍卖,游戏等。
所谓“真正”,我是指数据不仅仅是写在某个地方并持续轮询,而是实际上以某种方式流式传输到客户端。
所谓“半”,我的意思是如果只有从服务器到客户端的流是实时的,那么从客户端到服务器的消息就不是实时的也可以接受。
对于客户端和服务器之间的通信,我想坚持使用纯HTTP(AJAX),而不是其他协议。
通过手动刷新输出缓冲区,可以将数据流发送到客户端。
问题是要连接哪些服务器端脚本?
一旦连接成功,如何进行阻塞读取而不是轮询更改?
共享内存(shmop)扩展可以工作,但它不跨平台。
也许memcached会起作用?但我不确定是否有一种方法可以进行阻塞读取,因此又回到了轮询 - 尽管我确信memcached非常快,但我不喜欢连续轮询的想法。
有什么想法吗?

我不是指推送 - 我正在寻找一种在服务器端打开流/管道/端口/通道/某些东西并向其写入的方法,任何当前连接到该流/东西的其他脚本都可以以阻塞模式从中读取,然后将结果写入持续运行的HTTP请求并刷新。 - mindplay.dk
3个回答

4

PHP不适合实现实时数据流。 PHP非常慢,而且不适合构建多线程应用程序。 您最好使用像Python或Java这样的语言实现完整的套接字服务器。

话虽如此,我强烈建议您查看NodeJS:http://nodejs.org/

它使用基于异步事件的I/O模型,而不是让线程在事件循环中阻塞。 NodeJS服务器是用Javascript编写的。 NodeJS快速、可扩展且学习曲线低。

客户端将使用长轮询Ajax请求连接到NodeJS HTTP服务器。 PHP可以直接连接到NodeJS并推送通知。 或者PHP可以写入消息队列、数据库、memcache等,并且NodeJS会轮询这些数据存储以获取更新,并向客户端发送新消息。

当轮询更新时,您可能需要编写自己的守护程序作为NodeJS与MySQL、memcached等之间的中间件。 NodeJS将保持与守护进程的套接字打开。 守护进程将轮询数据存储以获取更新,并将更新发送到NodeJS。 然后,NodeJS HTTP服务器将向客户端发送这些更新。

请参见此教程,了解实现实时Twitter流的方法:http://net.tutsplus.com/tutorials/javascript-ajax/learning-serverside-javascript-with-node-js/


1
这正是Node.js的用途。 - JohnO
8
你关于 PHP 速度慢的观点是错误的。但我必须承认,它可能并不适用于此类并行/多线程应用程序的设计。回答被接受了。 - mindplay.dk
Node.js 不是单线程的。http://rickgaribay.net/archive/2012/01/28/node-is-not-single-threaded.aspx - mindplay.dk
3
“对于‘PHP速度慢的错误观点’我赞成+1。事实并非如此。虽然它在线程方面存在一些限制,也肯定不适用于持久连接,但它并不慢。” - DougW
看看帖子的日期。PHP在V8中肯定比Java、Python和JS慢,而且在2011年更是如此。 - Simian
答案已经非常过时了。PHP 5->7带来了巨大的性能提升,7->8又带来了另一次增长,加上JIT编译器(需要正确的类型使用)。通常情况下,PHP 8比Python快3-4倍,当进行性能优化时可能会更快。 在许多任务中,JAVA比PHP更快,尽管新的JIT编译器可能会缩小差距。 就内存而言,PHP比JAVA更加高效。PHP可以用作高性能高级语言,包括多线程和非阻塞IO。 - John

2
如果您正在使用HTML和JavaScript,则需要WebSockets。如果是Flash或其他任何东西,则需要普通的TCP套接字。
两者的想法都是运行一个服务器文件(用PHP编写),等待连接。一旦它连接到一个或多个客户端,数据就可以双向推送。有一些PHP WebSocket项目可供选择。请查看这个:

http://code.google.com/p/phpwebsocket

还有一个叫做Skeleton的框架,我一直在为它做贡献,它内置了一个WebSocket服务器库。不过目前还处于不稳定阶段。

http://code.google.com/p/skeleton

不幸的是,WebSockets仍然是一项新技术,因此并不被所有浏览器支持。正如@Christian提到的那样,您可能希望使用Socket.IO库。

1
我最近发现了Ratchet - 一个非常好的、干净的、简单的PHP WebSockets服务器实现。 - mindplay.dk
2
我撤回之前的说法 - Ratchet 是个好主意,但是 PHP 本身不适合用作 socket 服务器进行实时应用 - 这篇文章解释了为什么。 - mindplay.dk

0
如果您想在PHP和另一种语言(例如C++应用程序)之间进行通信,您可能需要了解Apache Thrift(http://thrift.apache.org/)。Apache Thrift在Facebook上被广泛用于“可扩展的跨语言服务开发”。
编辑:我可能会使用Apache Thrift与监听端口80的Twisted应用程序进行通信,并让浏览器使用长轮询或websocket连接到Twisted应用程序。您可能还需要了解Socket.IO,它是一个专为实时应用程序设计的跨浏览器Websocket实现。
基本上,您将使您的应用程序通过Thrift推送到Twisted Web服务器,然后将消息传递给任何打开的连接。
  • 克里斯蒂安

我并不认为这值得花费精力——PHP根本就不是为这种任务而设计的。它的设计理念是基于HTTP生命周期的:一个无状态的请求/响应模型。对于实时/套接字应用程序来说,NodeJS是一个更安全的选择,而且现在语言障碍也不那么严重了,因为有很多编译成JavaScript并简单地使用Node/V8作为虚拟机的优秀语言。 - mindplay.dk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接