• PHP Socket编程 之 fsockopen指定ip获取远程数据 及 301自动跳转


    当域名与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
    ";
    		/* 最终的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 . "
    ";
    		}
    		$out .= "Connection: close
    
    ";
    		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, "
    
    ");
    		$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:(.*?)
    /", $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;
    	}
    }
    

    https://actom.me/blog/php%E4%BD%BF%E7%94%A8fsockopen%E6%8C%87%E5%AE%9Aip%E9%80%9A%E8%BF%87get%E6%88%96%E8%80%85post%E8%8E%B7%E5%8F%96%E8%BF%9C%E7%A8%8B%E6%95%B0%E6%8D%AE.html/comment-page-1

  • 相关阅读:
    Geoserver发布缓存切片(制定Gridsets)
    Oralce Spatial
    判断ArcSDE是否安装成功
    sqlserver操作geography方法
    ArcGIS Server 基于Token安全验证
    ArcGIS Server配置端口
    贝叶斯推断
    加密算法
    互联网协议认识
    yocto config mk.fs.ext4
  • 原文地址:https://www.cnblogs.com/7qin/p/13296846.html
Copyright © 2020-2023  润新知