我现在想实现的功能就是用ajax+php判断一个列表页面例如list.php有没有更新(即有没有新的链接出现)我目前用的办法是用php的curl请求这个列表页面,只返回header部分不返回body, 如果返回的header当中的:Content-Length的长度和上一次的不一样,再请教一次并返回body,用正则来检查是否有新的链接出现。不知道有没有比这更快的方法。?

解决方案 »

  1.   

    只返回header部分不返回body,这个不现实,原理我已经解释过了。当curl只是取回header的时候,实际上body已经到达你的主机,只不过被curl丢弃,没有返回给你。根据长度判断是不准确的,也不是每次都能取得长度。
    如果是自己的站点,不妨在所有引起页面变化的操作上加一个步骤,
    将XX页面变化时间存储到数据库,ajax可以通过一个检测xx页面更新时间的后台程序获取信息。静态页如果没更新,会返回304
      

  2.   

    do_fork您的所有问题都是对的,唯独这个问题我认为不对,如果我的说法有问题还请指教:麻烦看一下这个帖子您就明白了:http://bbs.blueidea.com/thread-2908061-1-2.html
      

  3.   

    那个帖子里面是自己写的socket,接收到特定数据之后就直接断开了,curl已经把socket请求封装好,所以你控制不了
      

  4.   

    这段代码我试过了
    <?php
    function getFileSize($url){
        $url = parse_url($url);
        if($fp = @fsockopen($url['host'],empty($url['port'])?80:$url['port'],$error)){
            fputs($fp,"GET ".(empty($url['path'])?'/':$url['path'])." HTTP/1.1\r\n");
            fputs($fp,"Host:$url[host]\r\n\r\n");
            while(!feof($fp)){
                $tmp = fgets($fp);
                if(trim($tmp) == ''){
                    break;
                }else if(preg_match('/(Content-Length.*)/si',$tmp,$arr)){
                    return trim($arr[1]);
                }   
            }   
            return null;
        }else{
            return null;
        }   
    }
    echo getFileSize("http://www.baidu.com/")
    ?>
    可是wireshark抓包告诉我,它并没有起作用,实际上还是照单全收了,
    TCP通信是存在一个window的,只有window满了,对方才会停止发包,
    通常单个page的大小都很有限,只有几K,而window超过这个大小,
    所以即使你自己写socket,读到length就立即关闭socket,但是很遗憾,
    在你关闭socket之前,数据已经到达你的主机,不论你是否真的需要这部分数据。对于若干兆字节的url,这个方式有效,但是对于只有几K的url,没有用的,
    读取到header之外的东西不可避免,支持HEAD的web站点并不多。你可以用tcpdump或者wireshark抓包看看,是不是只读取了headers。
    此外,keepalive也是个问题,在读取到一定字节后就关闭socket,
    会造成keepalive失效,导致每次向同一IP发送http请求时都必须重新建立socket连接,
    这个开销是很大的。
    如果很在意节省带宽,不太在意效率,可以考虑用C写一个扩展,
    用setsockopt设置TCP窗口大小为一个较小的数值wireshark抓来的数据
    GET / HTTP/1.1
    Host:www.baidu.com
    HTTP/1.1 200 OKDate: Sat, 21 Nov 2009 09:17:58 GMTServer: BWS/1.0Content-Length: 3520Content-Type: text/html;charset=gb2312Cache-Control: privateExpires: Sat, 21 Nov 2009 09:17:58 GMTSet-Cookie: BAIDUID=7B14CFF75A3DC12D4A590E53760BBA2F:FG=1; expires=Sat, 21-Nov-39 09:17:58 GMT; path=/; domain=.baidu.comP3P: CP=" OTI DSP COR IVA OUR IND COM "<html><head><meta http-equiv=Content-Type content="text/html;charset=gb2312"><title>..................      </title><style>body{margin:4px 0}p{margin:0;padding:0}img{border:0}td,p,#u{font-size:12px}#b,#u,#l td,a{font-family:arial}#kw{font:16px Verdana;height:1.78em;padding-top:2px}#b{height:30px;padding-top:4px}#b,#b a{color:#77c}#u{padding-right:10px;line-height:19px;text-align:right;margin:0 0 3px !important;margin:0 0 10px}#sb{height:2em;width:5.6em}#km{height:50px}#l{margin:0 0 5px 15px}#l td{padding-left:107px}p,table{width:650px;border:0}#l td,#sb,#km{font-size:14px}#l a,#l b{margin-right:1.14em}a{color:#00c}a:active{color:#f60}#hp{position:absolu
    te;margin-left:6px}#lg{margin:-26px 0 -44px}#lk{width:auto;line-height:18px;vertical-align:top}form{position:relative;z-index:9}</style></head>
    <body><div id=u><a href=http://passport.baidu.com/?login&tpl=mn>....</a></div><center><img src=http://www.baidu.com/img/baidu_logo.gif width=270 height=129 usemap="#mp" id=lg><br><br><br><br><table cellpadding=0 cellspacing=0 id=l><tr><td><div id=m><a 
    onclick=s(this) href=http://news.baidu.com>..&nbsp;..</a><b>..&nbsp;..</b><a onclick=s(this) href=http://tieba.baidu.com>..&nbsp;..</a><a onclick=s(this) href=http://zhidao.baidu.com>..&nbsp;..</a><a onclick=s(this) href=http://mp3.baidu.com>MP3</a><a onclick=s(this) href=http://image.baidu.com>..&nbsp;..</a><a onclick=s(this) href=http://video.baidu.com>..&nbsp;..</a></div></td></tr></table>
    <table cellpadding=0 cellspacing=0 style="margin-left:15px"><tr valign=top><td style="height:62px;padding-left:92px" nowrap><form name=f action=s><input type=text name=wd id=kw size=42 maxlength=100> <input type=submit value=........ id=sb><span id=hp><a href=/gaoji/preferences.html>....</a><br><a href=/gaoji/advanced.html>....</a></span></form></td></tr></table>
    <p id=km><a href=http://hi.baidu.com>....</a>&nbsp;&nbsp;<a href=http://www.hao123.com>hao123</a>&nbsp;|&nbsp;<a href=/more/>....<span style="font-family:....">>></span></a></p>
    <p style=height:60px><table cellpadding=0 cellspacing=0 id=lk><tr><td></td></tr></ta
    ble></p>
    <p style=height:30px><a onClick="this.style.behavior='url(#default#homepage)';this.setHomePage('http://www.baidu.com')" href=http://utility.baidu.com/traf/click.php?id=215&url=http://www.baidu.com>..............</a></p><p style=height:14px><a href=http://e.baidu.com>............</a> | <a href=http://top.baidu.com>..........</a> | <a href=http://home.baidu.com>........</a> | <a href=ht
    tp://ir.baidu.com>About Baidu</a></p><p id=b>&copy;2009 Baidu <a href=http://www.baidu.com/duty/>..............</a> <a href=http://www.miibeian.gov.cn target=_blank>..ICP..030173..</a> <img src=http://gimg.baidu.com/img/gs.gif></p><map name=mp><area shape=rect coords="43,22,227,91" href=http://hi.baidu.com/baidu/ target=_blank title="........ ........"></map></center></body>
    <script>var w=document.f.wd;function s(o){if(w.value.length>0){var h=o.href;var q=encodeURIComponent(w.value);if(h.indexOf("q=")!=-1){o.href=h.replace(new RegExp("q=[^&$]*"),"q="+q)}else{o.href+="?q="+q}}};(function(){if(new RegExp("q=([^&]+)").test(location.search)){w.value=decodeURIComponent(RegExp.$1)}})();if(navigator.cookieEnabled&&!/sug?=0/.test(document.cookie)){document.write('<script src=http://www.baidu.com/js/bdsug.js?v=1.1.0.3><\/script>')};if(window.attachEvent){window.attachEvent("onload",function(){w.focus();})}else{window.addEventListener('load',function(){w.focus()},true)};window.onunload=function(){};</script></html><!--
    0e94a8fd6438cdd2-->
      

  5.   

    注意看wireshark抓来的包,并没有只读取头部
      

  6.   

    range跟head一样,可以被server忽略掉,实际上www.baidu.com两者都忽略。如果range被接受了,返回的状态码是206,而不是200
      

  7.   

    服务器就不是分着发的,你有什么理由让服务器只发头呢?只能丢掉body,第二次你在丢掉head。这是何苦呢。
      

  8.   


    静态文件,如xxx.jpeg时,一般不会忽略,普通页或者动态页,可能会被当作GET解释。
    telnet www.baidu.com 80
    HEAD / HTTP/1.1,返回整个页面,并且等待下一个命令
    HEAD / HTTP/1.0,返回整个页面,并且立即关闭socket