Comet推送的两种方式(转)

本文介绍了两种实现实时数据推送的技术方案:长轮询和iframe流。这两种方案都允许服务器主动向客户端推送数据,实现类似实时聊天的功能。文章提供了详细的PHP服务端代码和JavaScript客户端代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

因公司做项目要求有一个面要实时获取最新数据。效果类似于实时聊天,或者淘宝支付页面(当手机上支付成功后)会自动跳转,还有就是微信手网页版(当用手机扫了页面上的二维码并确定后)也会自动跳转。

经过上百度和谷歌查询找到了一些有用的信息,现记录下来方便查阅。

comet相关资料:http://www.ibm.com/developerworks/cn/web/wa-lo-comet/

Comet是一种用于web的推送技术,能使服务器能实时地将更新的信息传送到客户端,而无须客户端发出请求,目前有两种实现方式:长轮询(long-polling)和iframe流(streaming)。

一、长轮询

长轮询就是客户端发起ajax请求,服务端会挂起该请求(通过循环),直到条件触发使服务器返回,在服务器返回前客户端一直处于pending,等待服务器返回。

长轮询可以减少客户端的无用请求,不过服务端的压力会大一些。另外可以采用websocket实现推送,不过兼容性会差些,有些浏览器不支持websocket。

服务端代码:

1<?php 
2//server.php 服务端  
3set_time_limit(0); 
4$filename './phplog.com/data.txt'
5//模拟新消息到来 
6if (!empty($_GET['m'])) { 
7    file_put_contents($filename$_GET['m']); 
8    exit(0); 
9
10$old filemtime($filename); 
11$cur filemtime($filename); 
12while $cur <= $old) { 
13    usleep(500000);//休息500ms 
14    clearstatcache(); 
15    $cur filemtime($filename); 
16
17echo file_get_contents($filename
18 ?> 

客户端代码:

1<!doctype html> 
2<html lang="en"
3<head
4    <meta charset="UTF-8"
5    <script src="../phplog.com/jquery-1.9.0.min.js"></script
6    <title>PHP日志</title>
7</head
8<body
9    <button id="click1">click1</button
10    <script
11    var sending=false; 
12    $(function(){ 
13        $("#click1").click(function(){ 
14            $.ajax({ 
15                type:"POST", 
16                url:"server.php", 
17                timeout:0, 
18                beforeSend:function(){ 
19                    if (sending) { 
20                        return false; 
21                    
22                    sending = true; 
23                }, 
24                data:"username=eddy&password=123456", 
25                success:function(data){ 
26                    alert(data); 
27                }, 
28                error:function(data){ 
29                    
30                }, 
31                complete:function(){ 
32                    sending=false; 
33                    $("#click1").click(); 
34                
35            }); 
36        }); 
37    }); 
38    </script
39</body
40</html

点击click1按钮,发起请求,等待服务端返回(新消息到来)。此时可通过访问 /server.php?m=1234568798798000 模拟消息到达,消息到达服务端返回数据,客户端弹出消息内容。

二、iframe流

iframe 是很早就存在的一种 HTML 标记, 通过在 HTML 页面里嵌入一个隐蔵帧,然后将这个隐蔵帧的 SRC 属性设为对一个长连接的请求,服务器端就能源源不断地往客户端输入数据。

通过iframe里的内容进行长时间的请求,当需要传输内容时通过调用父页面js方法来实现页面展示,以此达到comet所需要的效果。

使用iframe流的一个不足就是在IE、opera、chrome浏览器下,始终会显示下载没完成,并且鼠标及浏览器上的那个圈一直在转动,在 IE678下,google的大牛们通过使用“htmlfile”解决了这个问题,IE9我试了,并不支持”htmlfile”,当然IE9那个圈已经不 转了。但是opera、chrome不支持“htmlfile”,无法解决。

iframe的另一个问题就是请求的超时,我们需要判断当iframe超时时,对其刷新重新建立连接。在普通情况下,我们可以通过iframe的 onload事件进行刷新,当iframe连接内容超时时就会触发onload事件。在“htmlfile”下iframe却不支持onload,但是能 读取到iframe的readyState,当readyState为complete时即表示请求超时,所以我们可以通过setInterval来判断 iframe的readyState进行刷新。

后台代码:

1<?php
2header("Cache-Control: no-cache, must-revalidate");
3header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
4flush();
5?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
7<head>
8  <title>PHP日志</title>
9  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
10</head>
11<body>
12<script type="text/javascript">
13  // KHTML browser don't share javascripts between iframes
14  var is_khtml = navigator.appName.match("Konqueror") || navigator.appVersion.match("KHTML");
15  if (is_khtml)
16  {
17    var prototypejs = document.createElement('script');
18    prototypejs.setAttribute('type','text/javascript');
19    prototypejs.setAttribute('src','prototype.js');
20    var head = document.getElementsByTagName('head');
21    head[0].appendChild(prototypejs);
22  }
23  // load the comet object
24  var comet = window.parent.comet;
25</script>
26<?php
27while(1) {
28  echo '<script type="text/javascript">';
29  echo 'comet.printServerTime('.time().');';
30  echo '</script>';
31  flush(); // used to send the echoed data to the client
32  sleep(1); // a little break to unload the server CPU
33}
34?>
35</body>
36</html>

前端代码:

1<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3<head>
4<title>PHP日志</title>
5<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
6<script type="text/javascript">
7var comet = {
8    connection : false,
9    iframediv : false,
10    timer : 0,
11    initialize: function() {
12        if (!-[1,]) {
13            // For IE browsers
14            comet.connection = new ActiveXObject("htmlfile");
15            comet.connection.open();
16            comet.connection.write("<html>");
17            comet.connection.write("<script>document.domain = '"+document.domain+"'");
18            comet.connection.write("</html>");
19            comet.connection.close();
20            comet.iframediv = comet.connection.createElement("div");
21            comet.connection.appendChild(comet.iframediv);
22            comet.connection.parentWindow.comet = comet;
23            comet.iframediv.innerHTML = "<iframe id='comet_iframe' name='comet_iframe' src='./backend.php'></iframe>";
24            var comet_iframe = comet.connection.getElementById("comet_iframe");
25            comet.timer = window.setInterval(function(){
26                if(comet_iframe.readyState === "complete"){
27                    comet_iframe.src = comet_iframe.src;
28                }
29            },1000*65)
30        }else{
31            comet.connection = document.createElement('iframe');
32            comet.connection.onload = function(){
33                comet.connection.src = comet.connection.src;
34            }
35            comet.connection.setAttribute('id','comet_iframe');
36            comet.connection.setAttribute('src','./backend.php');
37            comet.connection.style.display = "none";
38            document.body.appendChild(comet.connection);
39        }
40    },
41    // this function will be called from backend.php 
42    printServerTime: function (time) {
43        document.getElementById('content').innerHTML = time;
44    },
45    onUnload: function() {
46        if (comet.connection) {
47            comet.connection = false; // release the iframe to prevent problems with IE when reloading the page
48        }
49    }
50}
51window.onload = function(){
52    comet.initialize();
53}
54window.onbeforeunload = function(){
55    comet.onUnload();
56}
57</script>
58</head>
59<body>
60<div id="content">The server time will be shown here</div>
61</body>
62</html>

转载于:https://www.cnblogs.com/huojing/articles/3835441.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值