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

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

问题描述

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

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

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

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

解决方案

它比我最初想象的要简单.).

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

msgsrv.php

<?php如果(兰特(1,3)== 1){/* 假错误 */header("HTTP/1.0 404 未找到");死();}/* 在随机秒数 (2-10) 后发送一个字符串 */睡眠(兰特(2,10));echo("嗨!有一个随机数:" .rand(1,10));?>

注意:对于真实站点,在像 Apache 这样的常规 Web 服务器上运行它会很快占用所有工作线程"并使其无法响应其他请求.. 有办法解决这个问题,但它是建议在 Python 的 twisted 之类的东西中编写长轮询服务器",它不依赖于每个线程要求.cometD 是一种流行的(有多种语言版本),Tornado 是一个专门为此类任务而设计的新框架(它是为 FriendFeed 的长轮询代码而构建的)……但作为一个简单的例子,A​​pache 更胜一筹比够用!这个脚本可以很容易地用任何语言编写(我选择了 Apache/PHP,因为它们很常见,我碰巧在本地运行它们)

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

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

1 秒 setTimeout() 是一个非常基本的速率限制器,没有它也能正常工作,但是如果 msgsrv.php always立即返回(例如,出现语法错误)——你淹没了浏览器,它很快就会冻结.最好检查文件是否包含有效的 JSON 响应,和/或保持每分钟/秒的请求总数,并适当暂停.

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

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

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

<头><title>BargePoller</title><script src="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js" type="text/javascript" charset="utf-8"></脚本><style type="text/css" media="screen">正文{背景:#000;颜色:#fff;字体大小:.9em;}.msg{ 背景:#aaa;填充:.2em;边框底部:1px #000 实心}.old{ 背景颜色:#246499;}.new{ 背景色:#3B9957;}.error{ 背景色:#992E36;}</风格><script type="text/javascript" charset="utf-8">函数添加味精(类型,味精){/* 添加div的简单助手.type 是 CSS 类的名称(旧/新/错误).msg 是 div 的内容 */$("#messages").append("<div class='msg "+ type +"'>"+ msg +"</div>");}函数 waitForMsg(){/* 这请求 url "msgsrv.php"当它完成(或错误)*/$.ajax({类型:获取",url: "msgsrv.php",async: true,/* 如果设置为非异步,浏览器将页面显示为正在加载.."*/缓存:假,timeout:50000,/* 超时毫秒 */成功:函数(数据){/* 当对 barge.php 的请求完成时调用 */addmsg("new", 数据);/* 添加对 .msg div 的响应(使用new"类)*/设置超时(waitForMsg,/* 请求下一条消息 */1000/* ..1 秒后 */);},错误:函数(XMLHttpRequest,textStatus,errorThrown){addmsg("error", textStatus + " (" + errorThrown + ")");设置超时(waitForMsg,/* 后重试.. */15000);/* 毫秒 (15 秒) */}});};$(document).ready(function(){等待消息();/* 启动初始请求 */});<身体><div id="消息"><div class="msg old">BargePoll 消息请求者!

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.

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

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!

解决方案

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).

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));
?>

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)

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)

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.

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.

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

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屋!

查看全文
相关文章
PHP最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆