当域名与ip不相符,又无法修改系统hosts时,我们需要指定ip来获取远程数据,通过搜索php curl相关资料,未发现可用方法,故写了如下两个函数。
函数支持get或者post方式,301自动跳转,支持自定义header,仅支持ipv4的http协议。
代码已集成到AlonePHP中。
/* http_get_with_ip,用于ip解析错误或者需要指定ip的时候以get方式获取数据
* @param string $url 远程地址
* @param string $ip 需要访问的ip
* @param array $header 需要添加的其它header参数
* @return string|boolean 返回获取的内容,访问失败返回false
*/
function http_get_with_ip($url, $ip = '', $header = array()) {
return curl_post_with_ip($url, null, $ip, $header);
}
/* http_post_with_ip,用于ip解析错误或者需要指定ip的时候以post方式获取数据
* @param string $url 远程地址
* @param array|null $post_data 以post方式提交数据,如果此参数为null,则使用get方式
* @param string $ip 需要访问的ip
* @param array $header 需要添加的其它header参数
* @return string|boolean 返回获取的内容,访问失败返回false
*/
function http_post_with_ip($url, $post_data = null, $ip = '', $header = array()) {
/* 最大循环跳转次数 */
$loop_max_count = 5;
static $loop_count = 0;
$errstr = '';
$errno = '';
/* 解析URL */
$url_array = parse_url($url);
if ($url_array === false) {
$loop_count = 0;
return false;
}
$host = $url_array['host'];
/* 域名解析失败则退出 */
if (!$host) {
$loop_count = 0;
return false;
}
/* 获取端口 */
$port = isset($url_array['port']) ? $url_array['port'] : 80;
/* 获取ip */
if ($ip === '') {
$ip = gethostbyname($host);
}
$fp = fsockopen($ip, $port, $errno, $errstr, 90);
if (!$fp) {
$loop_count = 0;
return false;
} else {
$out = (is_array($post_data) ? "POST" : "GET") . " {$url} HTTP/1.0\r\n";
/* 最终的header数组 */
$header_result = array();
$header_result['Host'] = $host;
/* 处理post数据 */
if (is_array($post_data)) {
$post_values = array();
foreach ($post_data as $key => $value) {
array_push($post_values, urlencode($key) . "=" . urlencode($value));
}
$post_content = implode("&", $post_values);
$header_result['Content-type'] = "application/x-www-form-urlencoded";
$header_result['Content-length'] = strlen($post_content);
}
/* 设置默认的header */
$header_result['User-Agent'] = "Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Firefox/31.0";
$header_result = array_merge($header_result, $header);
/* 载入用户的header */
foreach ($header_result as $key => $value) {
$out .= $key . ": " . $value . "\r\n";
}
$out .= "Connection: close\r\n\r\n";
if (is_array($post_data)) {
$out .= $post_content;
}
fputs($fp, $out);
$response = '';
while (($line = fread($fp, 4096))) {
$response .= $line;
}
fclose($fp);
//分离Header头信息
$pos = strpos($response, "\r\n\r\n");
$header_content = substr($response, 0, $pos);
$response = substr($response, $pos + 4);
if (preg_match("/HTTP\/\d\.\d (\d+) /", $header_content, $matches) !== 1) {
$loop_count = 0;
return false;
}
$http_status = $matches[1];
/* 如果是30x,就跳转 */
if ($http_status == 301 || $http_status == 302) {
if (preg_match("/Location:(.*?)\n/", $header_content, $matches) !== 1) {
$loop_count = 0;
return false;
}
$url = trim($matches[1]);
$loop_count++;
return curl_post_with_ip($url, $post_data, $ip, $header);
}
$loop_count = 0;
return $response;
}
}
这个方法不能,网上的方法,我看过主要是两种实现:
1、利用浏览器发送多个php请求实现多线程,其实就等于服务器开了多个php线程
2、利用pthread库,这个确实是可以的,但是不推荐用在web环境。
能实现多线程吗? php说不能多线程 貌似 网上又写了方法 。。求指点多线程