小编典典

如何实施基本的“长轮询”?

php

我可以找到许多有关LongPolling工作原理的信息例如this和this],但是没有_简单的_ 示例说明如何在代码中实现这一点。

我所能找到的就是cometd,它依赖于Dojo JS框架和相当复杂的服务器系统。

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

该示例不必是可伸缩的,安全的或完整的,只需要工作即可!


阅读 439

收藏
2020-05-26

共1个答案

小编典典

它比我最初想象的要简单。基本上,您只有一个页面不执行任何操作,直到您要发送的数据可用(例如,收到新消息)为止。

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

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这样的常规Web服务器上运行该站点将很快占用所有“工作线程”,并使它无法响应其他请求。有很多解决方法,但是建议编写Python的Twisted之类的“长轮询服务器”,它不依赖每个请求一个线程。cometD是一种流行的语言(有多种语言可用),而Tornado是专门为此类任务创建的新框架(它是为FriendFeed的长轮询代码构建的)…但是作为一个简单的示例,Apache绰绰有余!这个脚本可以很容易地用任何一种语言编写(我选择了Apache
/ PHP,因为它们很常见,而我恰巧是在本地运行它们)

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

以下是此类页面的示例。.加载页面后,它将发送对msgsrv.php文件的初始请求。如果成功,则将消息附加到#messagesdiv,然后在1秒钟后再次调用waitForMsg函数,触发等待。

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

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

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

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

<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>
2020-05-26