Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1202924
  • 博文数量: 272
  • 博客积分: 3899
  • 博客等级: 中校
  • 技术积分: 4734
  • 用 户 组: 普通用户
  • 注册时间: 2012-06-15 14:53
文章分类

全部博文(272)

文章存档

2012年(272)

分类: 网络与安全

2012-06-26 13:15:56

Comet 能够在HTTP协议上保持常连接,相对无状态的HTTP协议来说,更加可靠一点。但是由于实现技术还是基于HTTP协议,所以这种可靠性还是比较弱的。

Comet 最初是由Dojo Toolkit 的人提出的概念,使用 Server push 技术能够提高性能,改善用户体验。

因为如果使用 setInterval() 一直等待的时候,实际上是消耗了很多无所谓的时间和性能。 如果服务端能够主动告诉客户端,改变了什么,那么就能够有效提高效率。

关于Comet, 还有一个 Bayeux 协议,比较复杂,我觉得没啥必要整这个东西,有兴趣的可以看看
http://cometdproject.dojotoolkit.org/documentation/bayeux

摘自

In web developmentComet is a  to describe a  model in which a long-held  request allows a  to  data to a browser, without the browser explicitly requesting it. Comet is an  for multiple techniques for achieving this interaction. All methods have in common that they rely on browser-native technologies such as , rather than on proprietary plugins.

In theory, the Comet approach differs from the , in which a browser requests a complete web page or chunks of data to update a web page. However in practice, Comet applications typically use  with  to detect new information on the server. The concept predates the coining of the neologism, and is known by several other names, including Ajax Push, , Two-way-web, HTTP Streaming and  among others.

实现Comet 的方式有很多种,常见的有。

出于个人爱好,我不喜欢用iframe,而Ajax 又有跨域的限制,所以我使用动态加载script的办法来实现Comet

实现思路:

1. 使用javascript动态加载一个script

2. script指向我们服务端的php

3. php返回数据,并且移除掉刚才动态生成的script,同时生成一个新的script,继续加载服务端的地址

4. 如此循环就可以保持一个连接

值得注意的是关于 keep-alive

在HTTP/1.1的标准中个已经默认将所有的连接都设置为 keep-alive,直到服务器返回一个 Connection: close 为止。 HTTP/1.0中需要手动设置一下。

此外IE还有个问题就是cache的问题,IE真的是一个很矬的浏览器!!!

下面是我的实现代码:

client 端:

<html>
<head>

head>

<body>
<script type="text/javascript" >

var comet = {
author: "axis@ph4nt0m.org",
cometHandler: "cometHandler", // Do not Change this!

cometServer: "cometS.php",
timeout: 3000, //ms
requestData: "",
responseData: "",

request: function(cometServer, timeout, data){
// check params
if (typeof(cometServer) != "undefined"){
comet.cometServer = cometServer;
}

if (typeof(timeout) != "undefined"){
comet.timeout = timeout;
}

if (typeof(data) != "undefined"){
comet.requestData = data;
}

var handler = document.createElement("script");
handler.id = comet.cometHandler;

// IE must refresh cache
var d = new Date();
handler.src = comet.cometServer + "?" + comet.requestData + "×tamp=" + d.getTime();


// IE 太矬了,居然识别不到这个 onerror
handler.onerror = function(msg, file, line){
// alert(msg);
// free handler
var remover = document.getElementById(comet.cometHandler);
remover.parentNode.removeChild(remover);

// reconnect to server after 2 seconds
setTimeout(function(){ comet.request(); }, comet.timeout);

};

try {
document.getElementsByTagName("head")[0].appendChild(handler);
}
catch (e) {
document.getElementsByTagName("body")[0].appendChild(handler);
}
},

response: function(responseData){
var remover = document.getElementById(comet.cometHandler);
remover.parentNode.removeChild(remover);


if (typeof(responseData) != "undefined"){
comet.responseData = responseData;
}

comet.request();
comet.callback(responseData);

},

callback: function(responseData){
doSomething(responseData);
}

};

comet.request("cometS.php", 5000, "a=1\&b=2");


function doSomething(data){
var d = document.createElement("div");
d.innerHTML = data["Search Engines"][3];
document.body.appendChild(d);
}

script>

body>
html>

服务端:

$arr = array("Search Engines" =>
array (
    0=> "http//google.com",
    1=> "http//yahoo.com",
    2=> "http//msn.com/",
    3=> date(DATE_RFC822)),

"Social Networking Sites" =>
array (
    0 => "http//",
    1 => "http//",
    2 => "http//vkontakte.ru",)
);

sleep(5);

?>

comet.response();

可以看到,实现的代码很简洁。

使用方式很简单,加载了 comet 后,客户端的调用方法是:

comet.request(服务端的地址, 超时时间, queryString);

在服务端,只需要在代码里返回一个

comet.response(返回数据);

即可。

然后可以通过修改 callback 函数去对返回数据进行处理。

上面POC的运行效果:


这个POC的客户端会去请求服务器,服务器收到请求后,会等待5秒,然后才响应该请求。所以这是服务端主动去告诉客户端一些东西。和以往的 setInterval 不一样。

已知bug:如果在IE下连接出错,就会中断程序,因为检测不到onerror。在firefox下连接出错,会每隔3秒重试。

阅读(1989) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~