有没有一种方法可以从Web服务器向浏览器推送数据?

138
当然我知道Ajax,但Ajax的问题在于浏览器需要频繁轮询服务器以查找是否有新数据。这会增加服务器负载。是否有更好的方法(包括使用Ajax)可以不经常轮询服务器?

1
我不确定是否存在这样的解决方案。为了让应用程序在概念上更简单,我想你可以在轮询请求之上实现一个传输层,从而将轮询责任从应用逻辑中移除。也许已经有人实现了这个功能?<strong>编辑:</strong>显然它被称为<a href="http://en.wikipedia.org/wiki/Reverse_Ajax">反向Ajax</a>和<a href="http://en.wikipedia.org/wiki/Comet_(programming)">Comet</a>,但目前看来你必须自己实现它。有没有针对此功能的JavaScript库呢? - Anders Sandvig
1
@Rachel - 实时更新,让你可以看到其他人在做什么。对于像 StackOverflow 这样的网站以及像 Google 文档这样的协作 Web 应用程序非常有用。 - Itai Bar-Haim
1
在2016年进行这种操作的人可能会发现WebSockets是这种通信的更好选择。 - Shadow
18个回答

71

36

是的,它被称为 反向Ajax Comet 。Comet基本上是一个总称,用于描述不同的方法来打开长连接HTTP请求,以便将数据实时地推送到Web浏览器。我建议使用StreamHub Push Server,他们有一些很酷的演示,并且比其他服务器更容易入门。查看Comet和StreamHub入门教程,可以快速了解一下。您可以使用可免费下载的社区版,但仅限20个并发用户。商业版值得购买,因为它提供支持,还包括SSL和桌面.NET和Java客户端适配器。帮助可以通过Google Group获得,网上有很多好的教程,并且还有一个 GWT Comet适配器


1
一旦你开始实现它,你就会意识到有多少工作要做——重新连接、长轮询、流式 iframe、跨浏览器支持、HTTPS……这绝对是正确的方法。 - Corehpf
2
解释一下什么是Comet会有助于回答这个问题。 - Kevin Monk
1
@Satir:添加了一个快速解释。其他答案中有维基百科文章的链接。 - Nosrama

35

现在你应该使用WebSockets。这是一个2011年的标准,允许通过HTTP建立连接,然后将其升级为双向的基于消息的客户端-服务器通信。

你可以轻松地从Javascript中发起连接:

var ws = new WebSocket("ws://your.domain.com/somePathIfYouNeed?args=any");
ws.onmessage = function (evt) 
{
  var message = evt.data;
  //decode message (with JSON or something) and do the needed
};

服务器端的处理取决于您的技术堆栈。


3
WebSockets 和 Server-Sent Events(EventSource)之间的区别是什么?WebSockets 为双向通信提供了一个基于套接字的机制,它可以让浏览器和服务器在任何时候都能够交换数据。在 WebSockets 中,客户端和服务器都可以通过发送消息来与对方进行通信。Server-Sent Events(EventSource),也是一种从服务器推送数据到客户端的机制,但是它们只能用于服务器到客户端的单向消息传递。这使得它们非常适合用于实时更新,例如推送新闻或股票报价等情况。EventSource 还支持自定义事件类型和重连功能。总的来说,如果需要双向通信,则应使用 WebSockets。如果只需要单向消息传递,则可以考虑使用 Server-Sent Events。 - Ciro Santilli OurBigBook.com
8
我完全同意……使用HTTP进行双向通信就像想通过REST调用让马里奥跳上乌龟壳一样疯狂。对于简单的按钮推动,你不需要发出请求并等待响应……你真的不需要。HTTP是一个文档协议。超文本传输协议。Ajax Push是一种非常复杂的方式来绕过HTTP执行WebSocket本来能够做到的事情。停止幼稚行为,使用适合的工具来完成工作。 - Nick Steele

10

了解一下Comet(一个模仿Ajax清洁剂,并且它本身也是一种清洁剂)它基本上是“反向Ajax”。需要注意的是,这要求每个用户都有一个长连接的服务器连接来接收通知,因此在编写应用程序时要注意性能影响。

http://en.wikipedia.org/wiki/Comet_(programming)


6

6

W3C规范的最新版本http://www.w3.org/TR/2009/WD-eventsource-20091029/重定向到https://html.spec.whatwg.org/multipage/comms.html#server-sent-events。 - Ciro Santilli OurBigBook.com

5

除了Comet,使用Flash中的套接字是一个有趣的选择。


5
我强烈建议花一些时间在Comet上进行投资,但我不知道您可以使用的实际实现或库。对于涉及更新呼叫中心代理和呼叫队列状态的Web应用程序的“呼叫中心控制面板”,我们开发了一个内部解决方案,但它与您可以使用的库相去甚远。 我们所做的是在服务器上实现一个小型服务,该服务与电话系统通信,等待新事件并维护情况的快照。此服务提供一个小型Web服务器。我们的Web客户端通过HTTP连接到此Web服务器,并请求最后一张照片(以XML编码),显示它,然后再次请求新照片。此时Web服务器可以:返回新的照片(如果存在),阻止客户端等待一些事件发生并更改照片的某些秒数(在我们的设置中为30秒)。如果在那一点上没有生成事件,则返回相同的照片,只是为了保持连接活动并避免使客户端超时。这样,当客户端轮询时,最多在0到30秒内获取响应。如果已经生成新事件,则立即获取该事件;否则,阻塞直到生成新事件。基本上这是轮询,但是它是有点聪明的轮询,以避免过度使用Web服务器。如果Comet不是您的答案,我相信使用更广泛的AJAX或编码JSON可以更好地实现同样的想法。这是在AJAX时代之前设计的,因此有很多改进的空间。如果有人可以提供此实际轻量级实现,那太棒了!

4

2

您可以使用BlazeDS或LiveCycle服务器端与客户端上的Flash/Flex应用程序。数据可以使用RTMP连接推送到客户端。请注意,RTMP使用非标准端口。但是,如果端口被阻塞,您可以轻松地回退到轮询。


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