欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  php教程

解决PHP中fopen容易超时的问题

程序员文章站 2022-05-08 15:42:23
...

http://www.btmao.org 为了从远程读取网页内容,我们常常用需要用PHP打开网页文件,而当网页文件很大或者网页根本不存在的时候,我们发现使用fopen的方法经常会出现超时。于是我们需要一个更加稳定的方法来解决这个问题。 我们想到使用fsockopen来帮助我们完

http://www.btmao.org

为了从远程读取网页内容,我们常常用需要用PHP打开网页文件,而当网页文件很大或者网页根本不存在的时候,我们发现使用fopen的方法经常会出现超时。于是我们需要一个更加稳定的方法来解决这个问题。

我们想到使用fsockopen来帮助我们完成工作。fsockopen是定下在network function下的一个函数,他使用的是socket来打开文件。

解决PHP中fopen容易超时的问题resource fsockopen ( string $hostname [, int $port [, int &$errno [, string &$errstr [, float $timeout ]]]] )

我们定义了一个类叫做http,下面是详细的代码。

解决PHP中fopen容易超时的问题php
解决PHP中fopen容易超时的问题
class http
解决PHP中fopen容易超时的问题{
解决PHP中fopen容易超时的问题
function forge_http_packet($url, & $host, & $port, & $packet)
解决PHP中fopen容易超时的问题 {
解决PHP中fopen容易超时的问题
// sure about the $url is start with "http://"
解决PHP中fopen容易超时的问题

解决PHP中fopen容易超时的问题
$strpos = strpos($url, '/', 7);
解决PHP中fopen容易超时的问题
$filename = substr($url, $strpos, strlen($url) - $strpos);
解决PHP中fopen容易超时的问题
解决PHP中fopen容易超时的问题
$strpos2 = strpos($url, ':' , 7);
解决PHP中fopen容易超时的问题
if ($strpos2 == false || $strpos2 > $strpos)
解决PHP中fopen容易超时的问题 {
解决PHP中fopen容易超时的问题
$host = substr($url, 7, $strpos - 7);
解决PHP中fopen容易超时的问题
$port = 80;
解决PHP中fopen容易超时的问题 }
解决PHP中fopen容易超时的问题
else
解决PHP中fopen容易超时的问题 {
解决PHP中fopen容易超时的问题
$host = substr($url, 7, $strpos2 - 7);
解决PHP中fopen容易超时的问题
$port = intval(substr($url, $strpos2 + 1, $strpos - $strpos2 - 1));
解决PHP中fopen容易超时的问题 }
解决PHP中fopen容易超时的问题
解决PHP中fopen容易超时的问题
$encode_filename = str_replace(' ', '%20', $filename);
解决PHP中fopen容易超时的问题
解决PHP中fopen容易超时的问题
$packet = "GET ".$encode_filename." HTTP/1.1 ";
解决PHP中fopen容易超时的问题
$packet .= "Accept: */* ";
解决PHP中fopen容易超时的问题
$packet .= "Host: ".$host."";
解决PHP中fopen容易超时的问题
$packet .= "User-Agent: OpenWebSpider ";
解决PHP中fopen容易超时的问题 }
解决PHP中fopen容易超时的问题
解决PHP中fopen容易超时的问题
function chunked_result($chunked_html)
解决PHP中fopen容易超时的问题 {
解决PHP中fopen容易超时的问题
$html = "";
解决PHP中fopen容易超时的问题
$start_pos = 0;
解决PHP中fopen容易超时的问题
while ($start_pos strlen($chunked_html))
解决PHP中fopen容易超时的问题 {
解决PHP中fopen容易超时的问题
$final_pos = strpos($chunked_html, "", $start_pos);
解决PHP中fopen容易超时的问题
$chunked_length = $this->hex2dec(substr($chunked_html, $start_pos, $final_pos - $start_pos));
解决PHP中fopen容易超时的问题
$buf_html = substr($chunked_html, $final_pos + 2, $chunked_length);
解决PHP中fopen容易超时的问题
$html .= $buf_html;
解决PHP中fopen容易超时的问题
$start_pos = $final_pos + $chunked_length + 4;
解决PHP中fopen容易超时的问题 }
解决PHP中fopen容易超时的问题
return $html;
解决PHP中fopen容易超时的问题 }
解决PHP中fopen容易超时的问题
解决PHP中fopen容易超时的问题
function hex2dec($hexstr)
解决PHP中fopen容易超时的问题 {
解决PHP中fopen容易超时的问题
$num = 0;
解决PHP中fopen容易超时的问题
for ($i = 0 ; $i strlen($hexstr) ; $i++)
解决PHP中fopen容易超时的问题 {
解决PHP中fopen容易超时的问题
$num = $num * 16;
解决PHP中fopen容易超时的问题
if ($hexstr[$i] >= '0' && $hexstr[$i] '9')
解决PHP中fopen容易超时的问题
$num += ord($hexstr[$i]) - ord('0');
解决PHP中fopen容易超时的问题
if ($hexstr[$i] >= 'A' && $hexstr[$i] 'F')
解决PHP中fopen容易超时的问题
$num += ord($hexstr[$i]) - ord('A') + 10;
解决PHP中fopen容易超时的问题
if ($hexstr[$i] >= 'a' && $hexstr[$i] 'f')
解决PHP中fopen容易超时的问题
$num += ord($hexstr[$i]) - ord('a') + 10;
解决PHP中fopen容易超时的问题 }
解决PHP中fopen容易超时的问题
return $num;
解决PHP中fopen容易超时的问题 }
解决PHP中fopen容易超时的问题
解决PHP中fopen容易超时的问题
function read_from_url($url)
解决PHP中fopen容易超时的问题 {
解决PHP中fopen容易超时的问题
$total_len = 0;
解决PHP中fopen容易超时的问题
$this->forge_http_packet($url, $host, $port, $packet);
解决PHP中fopen容易超时的问题
$handle = fsockopen($host, $port, $errno, $errstr, 5);
解决PHP中fopen容易超时的问题
if ($handle) {
解决PHP中fopen容易超时的问题
fwrite($handle, $packet);
解决PHP中fopen容易超时的问题
解决PHP中fopen容易超时的问题
$result = "";
解决PHP中fopen容易超时的问题
while (!feof($handle)) {
解决PHP中fopen容易超时的问题
解决PHP中fopen容易超时的问题
stream_set_timeout($handle, 10);
解决PHP中fopen容易超时的问题
$buffer = fgets($handle, 4096); //4K per 20 sec
解决PHP中fopen容易超时的问题
$info = stream_get_meta_data($handle);
解决PHP中fopen容易超时的问题
if ($info['timed_out'])
解决PHP中fopen容易超时的问题 {
解决PHP中fopen容易超时的问题
break;
解决PHP中fopen容易超时的问题 }
解决PHP中fopen容易超时的问题
$total_len += strlen($buffer);
解决PHP中fopen容易超时的问题
$result .= $buffer;
解决PHP中fopen容易超时的问题
if ($total_len > 1000000)
解决PHP中fopen容易超时的问题 {
// more than 2M filesize, properly not correct url for news or list
解决PHP中fopen容易超时的问题
return "";
解决PHP中fopen容易超时的问题 }
解决PHP中fopen容易超时的问题 }
解决PHP中fopen容易超时的问题
fclose($handle);
解决PHP中fopen容易超时的问题
解决PHP中fopen容易超时的问题
$pos = strpos($result, "");
解决PHP中fopen容易超时的问题
$header = substr($result, 0, $pos + 4);
解决PHP中fopen容易超时的问题
解决PHP中fopen容易超时的问题
if (strncasecmp($result, "HTTP/1.0 302", 12) == 0 ||
解决PHP中fopen容易超时的问题
strncasecmp($result, "HTTP/1.1 302", 12) == 0 ||
解决PHP中fopen容易超时的问题
strncasecmp($result, "HTTP/1.0 301", 12) == 0 ||
解决PHP中fopen容易超时的问题
strncasecmp($result, "HTTP/1.1 301", 12) == 0)
解决PHP中fopen容易超时的问题 {
解决PHP中fopen容易超时的问题
$new_url_pos = strpos($result, " Location:");
解决PHP中fopen容易超时的问题
if ($new_url_pos === false) return "";
解决PHP中fopen容易超时的问题
$new_url_pos += 11;
解决PHP中fopen容易超时的问题
$new_url_pos2 = strpos($result, "", $new_url_pos);
解决PHP中fopen容易超时的问题
return $this->read_body_from_url(trim(substr($result,
解决PHP中fopen容易超时的问题
$new_url_pos, $new_url_pos2 - $new_url_pos + 1)));
解决PHP中fopen容易超时的问题 }
解决PHP中fopen容易超时的问题
else if (strncasecmp($result, "HTTP/1.0 4", 10) == 0 ||
解决PHP中fopen容易超时的问题
strncasecmp($result, "HTTP/1.1 4", 10) == 0 ||
解决PHP中fopen容易超时的问题
strncasecmp($result, "HTTP/1.0 5", 10) == 0 ||
解决PHP中fopen容易超时的问题
strncasecmp($result, "HTTP/1.1 5", 10) == 0)
解决PHP中fopen容易超时的问题 {
解决PHP中fopen容易超时的问题
$pos2 = strpos($result, "");
解决PHP中fopen容易超时的问题
return substr($result, 0, $pos2);
解决PHP中fopen容易超时的问题 }
解决PHP中fopen容易超时的问题
解决PHP中fopen容易超时的问题
if (strstr($header, "Transfer-Encoding: chunked") == false)
解决PHP中fopen容易超时的问题
return strstr($result, "");
解决PHP中fopen容易超时的问题
return $this->chunked_result(substr($result, $pos + 4, strlen($result) - ($pos + 4)));
解决PHP中fopen容易超时的问题 }
解决PHP中fopen容易超时的问题
return "";
解决PHP中fopen容易超时的问题 }
解决PHP中fopen容易超时的问题}
解决PHP中fopen容易超时的问题
?>

只需要调用上述类中的函数read_from_url($url)便可以完成工作。