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

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

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

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

这个例子不必是可伸缩的、安全的或完整的,它只需要工作

这比我最初想象的要简单。。基本上,在您想要发送的数据可用(例如,新消息到达)之前,您的页面不会执行任何操作

下面是一个非常基本的示例,它在2-10秒后发送一个简单的字符串。返回错误404的概率为1/3(在接下来的Javascript示例中显示错误处理)

msgsrv.php

<?php
if(rand(1,3)=1){
/*假装错误*/
标题(“未找到HTTP/1.0 404”);
模具();
}
/*在随机数秒(2-10)后发送字符串*/
睡眠(rand(2,10));
echo(“嗨!有一个随机数:”.rand(1,10));
?>

注意:对于一个真实的站点,在常规的web服务器(如Apache)上运行它将很快占用所有的“工作线程”,并使其无法响应其他请求。。有很多方法可以解决这个问题,但是建议用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秒的方式相同)

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

总之,使用jQuery框架的long_poller.htm代码:

<html>
<头>
<标题>驳船装卸工&lt/标题>
<脚本src=”http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js“type=“text/javascript”charset=“utf-8”&gt&lt/脚本>
<style type=“text/css”media=“screen”>
正文{背景:#000;颜色:#fff;字体大小:.9em;}
.msg{background:#aaa;padding:.2em;边框底部:1px#000 solid}
.old{背景色:#246499;}
.new{背景色:#3B9957;}
.错误{背景色:#992E36;}
&lt/风格>
<script type=“text/javascript”charset=“utf-8”>
函数addmsg(类型,msg){
/*添加div的简单助手。
type是CSS类的名称(旧/新/错误)。
msg是div的内容*/
$(“#消息”)。追加(
“<div class='msg'+type+”>“+msg+”</div>”
);
}
函数waitForMsg(){
/*这将请求url“msgsrv.php”
完成时(或错误)*/
$.ajax({
键入:“获取”,
url:“msgsrv.php”,
async:true,/*如果设置为非异步,浏览器将页面显示为“加载…”*/
cache:false,
超时:50000,/*以毫秒为单位的超时*/
成功:对barge.php的请求完成时调用函数(数据){/**/
addmsg(“new”,data);/*将响应添加到.msg div(使用“new”类)*/
设置超时(
waitForMsg,/*请求下一条消息*/
1000/*…1秒后*/
);
},
错误:函数(XMLHttpRequest、textStatus、errorshown){
addmsg(“错误”,textStatus+”(“+errorSprown+”));
设置超时(
waitForMsg,/*请在..之后重试*/
15000);/*毫秒(15秒)*/
}
});
};
$(文档).ready(函数(){
waitForMsg();/*启动初始请求*/
});
&lt/脚本>
&lt/头>
<车身>
<div id=“消息”>
<div class=“msg old”>
BargePoll消息请求者!
&lt/部门>
&lt/部门>
&lt/车身>
&lt/html>

发表评论