长轮询、Websockets、服务器推送事件(SSE)和Comet是什么?

1187

我尝试阅读一些文章,但目前对这些概念并不十分清晰。

有人能否尝试向我解释以下这些技术是什么:

  1. 长轮询
  2. 服务器发送事件
  3. Websockets
  4. Comet

每次我看到的一个共同点是,服务器保持连接打开并将数据推送到客户端。如何保持连接打开,客户端如何获取推送的数据?(客户端如何使用数据,也许一些代码可以帮助?)

现在,哪种技术应该用于实时应用程序?我一直听说websockets(使用socket.io [node.js库]),但为什么不能用PHP呢?


2
实时websocket还是webrtc?php有一个websocket库,您需要编写额外的代码才能使用ZMQ或套接字编程使其工作,nodeJs专为此而构建,因此很容易获得。websocket在php中不容易获得的原因是您必须运行额外的终端并保持其运行,以便websocket服务器随时可用,您将拥有两个服务器。而且,php的结构不像JavaScript那样是事件结构,这就是其中的原因,websocket使用事件结构来捕获和发送消息。 - PauAI
1
此外:Comet和ServerSent Events是PHP实现几乎实时(并非真正实时)的解决方案,而无需创建两个服务器。 - PauAI
4个回答

2284
  • 下面的示例中,客户端是浏览器,服务器是托管网站的Web服务器。

  • 在您理解这些技术之前,您必须先了解传统HTTP Web流量。

  • 普通HTTP:

    1. 客户端从服务器请求网页。
    2. 服务器计算响应。
    3. 服务器将响应发送给客户端。

    HTTP

    Ajax轮询:

    1. 客户端使用常规HTTP(参见上文中的HTTP)从服务器请求网页。
    2. 客户端收到所请求的网页并执行其中的JavaScript,该JavaScript以固定时间间隔(例如0.5秒)从服务器请求文件。
    3. 服务器计算每个响应并像正常的HTTP流量一样将其发送回来。

    Ajax Polling

    Ajax长轮询:

    1. 客户端使用常规HTTP(参见上文中的HTTP)从服务器请求网页。
    2. 客户端收到所请求的网页并执行其中的JavaScript,该JavaScript请求文件从服务器。
    3. 服务器不会立即响应所请求的信息,而是等待直到有的信息可用。
    4. 当有新信息可用时,服务器会响应新信息。
    5. 客户端接收新信息并立即向服务器发送另一个请求,重新启动该过程。

    Ajax Long-Polling

    HTML5服务器发送事件(SSE)/ EventSource:

    1. 客户端使用常规HTTP(参见上文中的HTTP)从服务器请求网页。
    2. 客户端收到所请求的网页并执行其中的JavaScript,该JavaScript打开与服务器的连接。
    3. 当有新信息可用时,服务器向客户端发送事件。

    • 大多数情况下,您需要实时的服务器到客户端流量
    • 您需要使用具有事件循环功能的服务器
    • 与其他域的服务器连接只有在正确设置CORS设置时才可能
    • 如果您想要了解更多信息,我发现这些非常有用:(文章)(文章)(文章)(教程)

    HTML5 SSE

    HTML5 Websockets:

    1. 客户端使用常规http(参见上文HTTP)请求网页。
    2. 客户端接收请求的网页并执行页面上的JavaScript,该JavaScript打开与服务器的连接。
    3. 现在,当新数据可用时,服务器和客户端可以互相发送消息。

      • 从服务器到客户端从客户端到服务器的实时流量
      • 您需要使用具有事件循环功能的服务器
      • 使用WebSockets可以连接到另一个域中的服务器。
      • 还可以使用第三方托管的websocket服务器,例如Pusher其他。这样,您只需要实现客户端部分,这非常容易!
    4. 如果你想阅读更多相关内容,我发现以下文章非常有用: (文章), (文章) (教程)。

    HTML5 WebSockets

    Comet:

    Comet是一组在HTML5之前使用流媒体和长轮询技术实现实时应用的技术集合。请参考维基百科这篇文章了解更多信息.


    现在, 为实时应用程序(需要编码)我该选择哪个? 我听说过很多关于websockets的事情(使用socket.io [一个node.js库]),但不能使用PHP吗?

    你可以使用PHP与WebSockets,查看Ratchet


    26
    太棒了!我正在研究SSE,并找到了这篇文章,它非常好-就像我已经比较了一些东西一样。您能否在这里也包括SSE,以便我们还可以交叉检查它与Websocket的区别? - index
    5
    两种解决方案都可以达到相同的效果,但机制不同。长轮询使用“普通”的http数据,SSE使用不同的底层协议,并且与长轮询相比需要不同的服务器设置。 - Tieme
    1
    为什么你说不要使用 Apache? - bobzer
    2
    你可以使用Apache,但很多人使用Node.js因为它有一个事件循环。但是对于Apache,请参见https://dev59.com/mGct5IYBdhLWcg3wSbjY。 - Tieme
    4
    @Tieme 我知道2013年是很久以前的事了,但我想指出SSE并没有使用不同的协议。它只是HTTP分块编码的一种变体,浏览器通过在套接字上设置TCP keepalive来适应它。与WebSockets相比,它也可以与HTTP/2一起使用。 - w00t
    显示剩余16条评论

    43

    Tieme花了很多心思写了他出色的答案,但我认为OP问题的核心是这些技术如何与PHP相关,而不是每种技术如何工作。

    除了明显的客户端HTML、CSS和Javascript之外,PHP是Web开发中使用最广泛的语言。然而,当涉及到实时应用程序时,PHP存在两个主要问题:

    1. PHP最初是一个非常基本的CGI。自从它的早期阶段以来,PHP已经取得了很大进展,但是这是逐步进行的。在成为今天的可嵌入和灵活的C库之前,PHP已经有数百万用户,其中大多数人依赖于其早期的执行模型,因此它尚未在内部实现稳定地尝试逃离CGI模型。即使命令行界面调用PHP库(Linux上的libphp5.so,Windows上的php5ts.dll等),它仍像CGI一样处理GET / POST请求。它仍像构建“页面”并结束其生命周期一样执行代码。结果,在PHP用户空间内,它对多线程或事件驱动编程的支持非常少,从而使它目前不适用于实时多用户应用程序。

    请注意,PHP确实有扩展程序为PHP用户空间提供事件循环(例如libevent)和线程(例如pthreads),但是非常非常少的应用程序使用它们。

    1. PHP仍然存在垃圾回收的重要问题。尽管这些问题一直在不断改善(可能是结束上述生命周期的最大步骤),但即使是最好的创建长时间运行的PHP应用程序的尝试也需要定期重新启动。这也使其难以用于实时应用。

    PHP 7将是解决这些问题的重大进步,并且似乎非常有前途成为实时应用程序平台。


    2
    一个小纠正:PHP一直是用C语言编写的,可以在这里看到:http://museum.php.net/php1/ 另外,“较少使用(但非常流行)”有些自相矛盾;也许你的意思是“更时尚”? - IMSoP
    1
    @IMSoP - 感谢您的更正。我已经使用PHP超过十年了,一直以为它的根源是Perl。PHP [history] (http://php.net/manual/en/history.php.php)页面明确支持它最初也是C语言编写的。我一有时间就会编辑我的回答。 - JSON
    我会删除有关Perl的部分,因为它与官方文档不太搭配,但这仍然是PHP早期开发中一个令人困惑的领域。 - JSON
    PHP 7似乎是实时应用程序的一个非常有前途的平台?PHP7对于实时应用程序有哪些改进/变化? - I'll-Be-Back
    @I'll-Be-Back - 修复了内存管理/垃圾回收、JIT编译等问题。 - JSON

    13

    轮询

    轮询是一种定期向服务器请求信息的技术,通常使用HTTP协议建立连接。轮询有两种类型:

    1. 短轮询
    2. 长轮询

    短轮询

    在短轮询中,客户端向服务器请求信息,服务器处理请求。如果服务器有客户端请求的数据,则它会返回所需的信息。但是,如果服务器没有可供客户端使用的数据,则服务器将返回一个空响应。在两种情况下,服务器都会在返回响应后关闭连接。即使在服务器发送空响应后,客户端仍会不断发出新的请求。这种机制增加了服务器的网络开销。

    长轮询

    在长轮询中,客户端可以请求服务器获取信息,但服务器可能不会立即响应。当服务器收到请求时,如果它没有适用于客户端的最新数据,则服务器保持请求处于打开状态并等待数据到达。当服务器接收到新数据时,它将立即向客户端传送响应并完成打开请求。然后,客户端可以在从服务器获取答案后发送另一个请求以获取新的更新。长轮询通过减少空响应的数量来降低成本。

    WebSocket

    WebSocket是一种协议,它在单个TCP连接上提供双向通信通道。WebSocket为客户端和服务器之间提供了持久连接,允许双方随时开始传输数据。WebSocket握手是客户端创建WebSocket连接的过程。如果操作成功,则服务器和客户端可以随时发送和接收数据。主要用于实时Web应用程序,如WhatsApp,Uber。

    服务器发送事件(SSE)

    与WebSocket不同,使用SSE无法从客户端向服务器发出请求,因为它是单向连接。当我们需要从服务器到客户端的“准实时”传输,或者如果服务器循环生成数据,则SSE是理想选择。

    Comet

    Comet是一种Web应用程序设计范例,它描述了服务器和Web浏览器之间使用本机HTTP方法进行连续的双向交互。 Comet是一个总称。 Ajax Push、HTTP Streaming和HTTP Server Push是可用于提供此事件驱动交互的一些HTTP机制。


    1
    你可以轻松地在网页应用中使用Node.JS来进行实时通信。当涉及到WebSockets时,Node.JS非常强大。因此,“通过Node.js进行PHP通知”将是一个很好的概念。
    看这个例子: 使用PHP和Node.js创建实时聊天应用

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