我可以找到很多关于长轮询如何工作的信息(例如,这个和这个),但没有简单的例子说明如何在代码中实现这一点。

我能找到的只有cometd,它依赖DojoJS框架和一个相当复杂的服务器系统。。

基本上,我将如何使用Apache来服务请求,以及我将如何编写一个简单的脚本(例如,用PHP)来“长轮询”服务器以获取新消息?

该示例不一定是可扩展的、安全的或完整的,它只需要工作即可!


当前回答

这是一个关于如何使用PHP&jQuery进行长时间轮询的5分钟精彩视频:http://screenr.com/SNH

代码与上面dbr的示例非常相似。

其他回答

Tornado是为长轮询而设计的,它在/examples/chatdemo中包含了一个非常小的(数百行Python)聊天应用程序,包括服务器代码和JS客户端代码。它的工作原理如下:

客户机使用JS请求更新,因为(最后一条消息的数量),服务器URLHandler接收这些消息并添加回调以响应客户机到队列。当服务器收到新消息时,onmessage事件将触发,循环通过回调,并发送消息。客户端JS接收消息,将其添加到页面,然后请求更新此新消息ID。

我用这个来掌握Comet,我还使用Java Glassfish服务器设置了Comet,并通过订阅cometdaily.com找到了许多其他示例

我有一个非常简单的聊天示例作为晃动的一部分。

编辑:(因为每个人都在这里粘贴代码)

这是使用长轮询和晃动的完整的基于JSON的多用户聊天。这是一个如何进行调用的演示,因此请忽略XSS问题。任何人都不应该在不首先清理它的情况下部署它。

请注意,客户端始终与服务器保持连接,一旦有人发送消息,每个人都应该立即大致看到。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!-- Copyright (c) 2008 Dustin Sallings <dustin+html@spy.net> -->
<html lang="en">
  <head>
    <title>slosh chat</title>
    <script type="text/javascript"
      src="http://code.jquery.com/jquery-latest.js"></script>
    <link title="Default" rel="stylesheet" media="screen" href="style.css" />
  </head>

  <body>
    <h1>Welcome to Slosh Chat</h1>

    <div id="messages">
      <div>
        <span class="from">First!:</span>
        <span class="msg">Welcome to chat. Please don't hurt each other.</span>
      </div>
    </div>

    <form method="post" action="#">
      <div>Nick: <input id='from' type="text" name="from"/></div>
      <div>Message:</div>
      <div><textarea id='msg' name="msg"></textarea></div>
      <div><input type="submit" value="Say it" id="submit"/></div>
    </form>

    <script type="text/javascript">
      function gotData(json, st) {
        var msgs=$('#messages');
        $.each(json.res, function(idx, p) {
          var from = p.from[0]
          var msg = p.msg[0]
          msgs.append("<div><span class='from'>" + from + ":</span>" +
            " <span class='msg'>" + msg + "</span></div>");
        });
        // The jQuery wrapped msgs above does not work here.
        var msgs=document.getElementById("messages");
        msgs.scrollTop = msgs.scrollHeight;
      }

      function getNewComments() {
        $.getJSON('/topics/chat.json', gotData);
      }

      $(document).ready(function() {
        $(document).ajaxStop(getNewComments);
        $("form").submit(function() {
          $.post('/topics/chat', $('form').serialize());
          return false;
        });
        getNewComments();
      });
    </script>
  </body>
</html>

这是PHP非常糟糕的选择之一。如前所述,您可以很快地将所有Apache工作人员绑在一起,这样做。PHP是为启动、执行和停止而构建的。它不是为开始而建造的,等等。。。执行,停止。你会很快让你的服务器陷入困境,并发现你有难以置信的扩展问题。

也就是说,您仍然可以使用PHP执行此操作,并且不会使用nginxHttpPushStreamModule杀死您的服务器:http://wiki.nginx.org/HttpPushStreamModule

您在Apache(或任何其他)前面设置nginx,它将负责保持并发连接的开放。您只需通过将数据发送到一个内部地址来响应有效负载,该地址可以通过后台作业来完成,也可以在收到新请求时将消息发送给正在等待的人。这可以防止PHP进程在长时间轮询期间处于打开状态。

这不是PHP独有的,可以使用nginx和任何后端语言来完成。并发开放连接的负载等于Node.js,所以最大的好处是它可以让你从NEEDING Node中解脱出来。

你会看到很多人提到其他语言库来完成长时间的投票,这是有充分理由的。PHP天生就不适合这种类型的行为。

我认为客户端看起来像一个普通的异步AJAX请求,但您希望它需要“很长时间”才能返回。

然后服务器看起来像这样。

while (!hasNewData())
    usleep(50);

outputNewData();

因此,AJAX请求将发送到服务器,可能包括上次更新的时间戳,以便hasNewData()知道您已经获得了哪些数据。然后,服务器在循环中休眠,直到新数据可用。一直以来,您的AJAX请求仍然连接,只是挂在那里等待数据。最后,当新数据可用时,服务器将其提供给AJAX请求并关闭连接。