2010-05-26 74 views
0
function httpGet($url, $followRedirects=true) { 
    global $final_url; 
    $url_parsed = parse_url($url); 
    if (empty($url_parsed['scheme'])) { 
     $url_parsed = parse_url('http://'.$url); 
    } 
    $final_url = $url_parsed; 

    $port = $url_parsed["port"]; 
    if (!$port) { 
     $port = 80; 
    } 
    $rtn['url']['port'] = $port; 

    $path = $url_parsed["path"]; 
    if (empty($path)) { 
     $path="/"; 
    } 
    if (!empty($url_parsed["query"])) { 
     $path .= "?".$url_parsed["query"]; 
    } 
    $rtn['url']['path'] = $path; 

    $host = $url_parsed["host"]; 
    $foundBody = false; 

    $out = "GET $path HTTP/1.0\r\n"; 
    $out .= "Host: $host\r\n"; 
    $out .= "User-Agent:  Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1) Gecko/20061010 Firefox/2.0\r\n"; 
    $out .= "Connection: Close\r\n\r\n"; 

    if (!$fp = @fsockopen($host, $port, $errno, $errstr, 30)) { 
     $rtn['errornumber'] = $errno; 
     $rtn['errorstring'] = $errstr; 

    } 
    fwrite($fp, $out); 
    while ([email protected]($fp)) { 

     $s = @fgets($fp, 128); 
     if ($s == "\r\n") { 
      $foundBody = true; 
      continue; 
     } 
     if ($foundBody) { 
      $body .= $s; 
     } else { 
      if (($followRedirects) && (stristr($s, "location:") != false)) { 
       $redirect = preg_replace("/location:/i", "", $s); 
       return httpGet(trim($redirect)); 
      } 
      $header .= $s; 
     } 
    } 

    fclose($fp); 

    return(trim($body)); 
} 

此代碼有時會發生無限循環。這裏有什麼問題?PHP Infine Loop問題

+1

發佈一個巨大的代碼塊可能不會給你任何幫助。減少顯示問題的代碼量是最好的。 – 2010-05-26 14:36:42

+0

這個函數獲取一個URL的html也做重定向。 有人有更好的功能,這樣做? file_get_contents與重定向? – 2010-05-26 14:42:58

回答

3

有一個在feof() documentation大,紅色的警告框:

警告

如果fsockopen()打開的連接沒有被服務器關閉,feof()將掛起。要解決此,見下面的例子:有FEOF)

示例#1處理超時(

<?php 
     function safe_feof($fp, &start = NULL) { 
      $start = microtime(true); 
      return feof($fp); 
     } 
     /* Assuming $fp is previously opened by fsockopen() */ 

     $start = NULL; 
     $timeout = ini_get('default_socket_timeout'); 

     while(!safe_feof($fp, $start) && (microtime(true) - $start) < $timeout) 
     { 
      /* Handle */ 
     } 
    ?> 

你也應該只寫或從文件指針中讀取,如果它是有效的(你是不是做了什麼,你只要設置一個錯誤消息): 這導致了第二個大紅色的警告框:

警告

如果傳遞的文件指針無效,則可能會出現無限循環,因爲feof()無法返回TRUE

更好

是:

$result = ''; 

if (!$fp = @fsockopen($host, $port, $errno, $errstr, 30)) { 
    $rtn['errornumber'] = $errno; 
    $rtn['errorstring'] = $errstr; 
} 
else { 
    fwrite($fp, $out); 
    while ([email protected]($fp)) { 
     //... 
    } 
    fclose($fp); 
    $result = trim(body); 
} 
return $result; 

最後一個要說:如果你遵循重定向與

if (($followRedirects) && (stristr($s, "location:") != false)) { 
    $redirect = preg_replace("/location:/i", "", $s); 
    return httpGet(trim($redirect)); 
} 

你從來沒有關閉文件指針。我認爲更好的是:

if (($followRedirects) && (stristr($s, "location:") != false)) { 
    $redirect = preg_replace("/location:/i", "", $s); 
    $result = httpGet(trim($redirect)); 
    break; 
} 
// ... 
return $result; 
+0

&start = NULL或$ start = NULL? – 2010-05-26 14:54:42

+0

是隊友改變了無效指針錯誤。 – 2010-05-26 14:56:03

0

如果連接仍然在tcp/ip流中打開,feof將返回false。

0
function httpGet($url, $followRedirects=true) { 
[...] 
       return httpGet(trim($redirect)); 
} 

沒有什麼能阻止你一次又一次地獲取相同的URL。

+0

只有在der是重定向時纔會調用它? – 2010-05-26 14:49:09