如何实施基本的“长轮询”? [英] How do I implement basic "Long Polling"?

查看:93
本文介绍了如何实施基本的“长轮询”?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I can find lots of information on how Long Polling works (For example, this, and this), but no simple examples of how to implement this in code.

我所能找到的只是 cometd ,它依赖于Dojo JS框架,以及一个相当复杂的服务器系统..

All I can find is cometd, which relies on the Dojo JS framework, and a fairly complex server system..

基本上,我如何使用Apache来处理请求,以及如何编写一个简单的脚本(例如,在PHP中)哪个会对服务器进行长时间轮询以获取新消息?

Basically, how would I use Apache to serve the requests, and how would I write a simple script (say, in PHP) which would "long-poll" the server for new messages?

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

The example doesn't have to be scaleable, secure or complete, it just needs to work!

推荐答案

这比我最初想的要简单..基本上是y你有一个什么都不做的页面,直到你要发送的数据可用(比如,新消息到达)。

It's simpler than I initially thought.. Basically you have a page that does nothing, until the data you want to send is available (say, a new message arrives).

这是一个非常基本的例子,它发送2-10秒后的简单字符串。三分之一的机会返回错误404(在即将到来的Javascript示例中显示错误处理)

Here is a really basic example, which sends a simple string after 2-10 seconds. 1 in 3 chance of returning an error 404 (to show error handling in the coming Javascript example)

msgsrv.php

<?php
if(rand(1,3) == 1){
    /* Fake an error */
    header("HTTP/1.0 404 Not Found");
    die();
}

/* Send a string after a random number of seconds (2-10) */
sleep(rand(2,10));
echo("Hi! Have a random number: " . rand(1,10));
?>

注意:对于一个真实的网站,在像Apache这样的常规网络服务器上运行它会很快占用所有工作线程并让它无法响应其他请求..有很多方法可以解决这个问题,但建议用像Python这样的 twisted ,每个请求不依赖于一个线程。 cometD 是一个受欢迎的版本(有多种语言版本),并且 Tornado 是专门为这些任务制作的新框架(它是为FriendFeed的长轮询代码而构建的)......但作为一个简单的例子,A​​pache更多比足够了!这个脚本很容易用任何语言编写(我选择了Apache / PHP,因为它们非常常见,我碰巧在本地运行它们)

Note: With a real site, running this on a regular web-server like Apache will quickly tie up all the "worker threads" and leave it unable to respond to other requests.. There are ways around this, but it is recommended to write a "long-poll server" in something like Python's twisted, which does not rely on one thread per request. cometD is an popular one (which is available in several languages), and Tornado is a new framework made specifically for such tasks (it was built for FriendFeed's long-polling code)... but as a simple example, Apache is more than adequate! This script could easily be written in any language (I chose Apache/PHP as they are very common, and I happened to be running them locally)

然后,在Javascript中,您请求上述文件( msg_srv.php ),并等待响应。当你得到一个,你就会对数据采取行动。然后你请求文件并再次等待,对数据采取行动(并重复)

Then, in Javascript, you request the above file (msg_srv.php), and wait for a response. When you get one, you act upon the data. Then you request the file and wait again, act upon the data (and repeat)

以下是这样一个页面的例子..当页面加载时,它发送 msgsrv.php 文件的初始请求。如果成功,我们将消息附加到 #messages div,然后在1秒后我们再次调用waitForMsg函数,这会触发等待。

What follows is an example of such a page.. When the page is loaded, it sends the initial request for the msgsrv.php file.. If it succeeds, we append the message to the #messages div, then after 1 second we call the waitForMsg function again, which triggers the wait.

1秒 setTimeout()是一个非常基本的速率限制器,没有它可以正常工作,但如果 msgsrv.php 总是立即返回(语法错误,例如) - 你淹没浏览器,它可以迅速冻结。最好检查文件是否包含有效的JSON响应,和/或保持每分钟/秒的运行总计请求,并适当地暂停。

The 1 second setTimeout() is a really basic rate-limiter, it works fine without this, but if msgsrv.php always returns instantly (with a syntax error, for example) - you flood the browser and it can quickly freeze up. This would better be done checking if the file contains a valid JSON response, and/or keeping a running total of requests-per-minute/second, and pausing appropriately.

如果页面错误,它会将错误附加到 #messages div,等待15秒然后再次尝试(与每条消息后等待1秒的方式相同)

If the page errors, it appends the error to the #messages div, waits 15 seconds and then tries again (identical to how we wait 1 second after each message)

这种方法的好处是它非常有弹性。如果客户端互联网连接中断,它将超时,然后尝试重新连接 - 这是轮询工作多长时间所固有的,不需要复杂的错误处理

The nice thing about this approach is it is very resilient. If the clients internet connection dies, it will timeout, then try and reconnect - this is inherent in how long polling works, no complicated error-handling is required

无论如何, long_poller.htm 代码,使用jQuery框架:

Anyway, the long_poller.htm code, using the jQuery framework:

<html>
<head>
    <title>BargePoller</title>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js" type="text/javascript" charset="utf-8"></script>

    <style type="text/css" media="screen">
      body{ background:#000;color:#fff;font-size:.9em; }
      .msg{ background:#aaa;padding:.2em; border-bottom:1px #000 solid}
      .old{ background-color:#246499;}
      .new{ background-color:#3B9957;}
    .error{ background-color:#992E36;}
    </style>

    <script type="text/javascript" charset="utf-8">
    function addmsg(type, msg){
        /* Simple helper to add a div.
        type is the name of a CSS class (old/new/error).
        msg is the contents of the div */
        $("#messages").append(
            "<div class='msg "+ type +"'>"+ msg +"</div>"
        );
    }

    function waitForMsg(){
        /* This requests the url "msgsrv.php"
        When it complete (or errors)*/
        $.ajax({
            type: "GET",
            url: "msgsrv.php",

            async: true, /* If set to non-async, browser shows page as "Loading.."*/
            cache: false,
            timeout:50000, /* Timeout in ms */

            success: function(data){ /* called when request to barge.php completes */
                addmsg("new", data); /* Add response to a .msg div (with the "new" class)*/
                setTimeout(
                    waitForMsg, /* Request next message */
                    1000 /* ..after 1 seconds */
                );
            },
            error: function(XMLHttpRequest, textStatus, errorThrown){
                addmsg("error", textStatus + " (" + errorThrown + ")");
                setTimeout(
                    waitForMsg, /* Try again after.. */
                    15000); /* milliseconds (15seconds) */
            }
        });
    };

    $(document).ready(function(){
        waitForMsg(); /* Start the inital request */
    });
    </script>
</head>
<body>
    <div id="messages">
        <div class="msg old">
            BargePoll message requester!
        </div>
    </div>
</body>
</html>

这篇关于如何实施基本的“长轮询”?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆