Php 检测代理服务器是否可用的最佳方法是什么?

Php 检测代理服务器是否可用的最佳方法是什么?,php,curl,proxy,Php,Curl,Proxy,我正在尝试编写一个工具来检查代理服务器是否已启动并可供使用。到目前为止,我在下面的类中提出了两个方法(我删除了对这个问题来说多余的setter和getter) 第一个方法使用cURL并尝试通过代理请求页面,第二个工具使用fsockopen仅尝试打开到代理的连接 class ProxyList { /** * You could set this to localhost, depending on your environment * @var string The

我正在尝试编写一个工具来检查代理服务器是否已启动并可供使用。到目前为止,我在下面的类中提出了两个方法(我删除了对这个问题来说多余的setter和getter)

第一个方法使用
cURL
并尝试通过代理请求页面,第二个工具使用
fsockopen
仅尝试打开到代理的连接

class ProxyList {
    /**
     * You could set this to localhost, depending on your environment
     * @var string The URL that the proxy validation method will use to check proxies agains
     * @see ProxyList::validate()
     */
    const VALIDATION_URL = "http://m.www.yahoo.com/robots.txt";
    const TIMEOUT        = 3;

    private static $valid = array(); // Checked and valid proxies
    private $proxies      = array(); // An array of proxies to check

    public function validate($useCache=true) {
        $mh       = curl_multi_init();
        $ch       = null;
        $handles  = array();
        $delay    = count($this->proxies) * 10000;
        $running  = null;
        $proxies  = array();
        $response = null;

        foreach ( $this->proxies as $p ) {
            // Using the cache and the proxy already exists?  Skip the rest of this crap
            if ( $useCache && !empty(self::$valid[$p]) ) {
                $proxies[] = $p;
                continue;
            }

            $ch = curl_init();
            curl_setopt($ch, CURLOPT_HTTP_VERSION,    CURL_HTTP_VERSION_1_1);
            curl_setopt($ch, CURLOPT_URL,             self::VALIDATION_URL);
            curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, true);
            curl_setopt($ch, CURLOPT_PROXY,           $p);
            curl_setopt($ch, CURLOPT_NOBODY,          true); // Also sets request method to HEAD
            curl_setopt($ch, CURLOPT_HEADER,          false);
            curl_setopt($ch, CURLOPT_FOLLOWLOCATION,  true);
            curl_setopt($ch, CURLOPT_TIMEOUT,         self::TIMEOUT);

            curl_multi_add_handle($mh, $ch);
            $handles[$p] = $ch;
        }

        // Execute the multi-handle
        do {
            curl_multi_exec($mh, $running);
            usleep($delay);
        } while ( $running );

        // Get the results of the requests
        foreach ( $handles as $proxy => $ch ) {
            $status = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE);

            // Great success
            if ( $status >= 200 && $status < 300 ) {
                self::$valid[$proxy] = true;
                $proxies[] = $proxy;
            }
            else {
                self::$valid[$proxy] = false;
            }

            // Cleanup individual handle
            curl_multi_remove_handle($mh, $ch);
        }

        // Cleanup multiple handle
        curl_multi_close($mh);

        return $this->proxies = $proxies;
    }

    public function validate2($useCache=true) {
        $proxies = array();

        foreach ( $this->proxies as $proxy ) {
            // Using the cache and the proxy already exists?  Skip the rest of this crap
            if ( $useCache && !empty(self::$valid[$proxy]) ) {
                $proxies[] = $proxy;
                continue;
            }

            list($host, $post) = explode(":", $proxy);

            if ( $conn = @fsockopen($host, $post, $errno, $error, self::TIMEOUT) ) {
                self::$valid[$proxy] = true;
                $proxies[] = $proxy;
                fclose($conn);
            } else {
                self::$valid[$proxy] = false;
            }
        }

        return $this->proxies = $proxies;
    }
}
类ProxyList{ /** *您可以将其设置为localhost,具体取决于您的环境 *@var string代理验证方法将用于再次检查代理的URL *@请参阅ProxyList::validate() */ 常量验证\u URL=”http://m.www.yahoo.com/robots.txt"; 常数超时=3; 私有静态$valid=array();//已检查且有效的代理 private$proxies=array();//要检查的代理数组 公共函数验证($useCache=true){ $mh=curl_multi_init(); $ch=null; $handles=array(); $delay=count($this->proxies)*10000; $running=null; $proxies=array(); $response=null; foreach($this->代理为$p){ //使用缓存和代理已经存在?跳过剩下的废话 如果($useCache&&!empty(self::$valid[$p])){ $proxies[]=$p; 继续; } $ch=curl_init(); curl_setopt($ch,CURLOPT_HTTP_VERSION,curl_HTTP_VERSION_1_1); curl_setopt($ch,CURLOPT_URL,self::VALIDATION_URL); curl_setopt($ch,CURLOPT_HTTPPROXYTUNNEL,true); curl_setopt($ch,CURLOPT_PROXY,$p); curl_setopt($ch,CURLOPT_NOBODY,true);//还将请求方法设置为HEAD curl_setopt($ch,CURLOPT_头,false); curl_setopt($ch,CURLOPT_FOLLOWLOCATION,true); curl_setopt($ch,CURLOPT_TIMEOUT,self::TIMEOUT); 卷曲多加手柄($mh,$ch); $handles[$p]=$ch; } //执行多句柄 做{ curl_multi_exec($mh,$running); usleep(延迟); }同时($运行); //获取请求的结果 foreach($作为$proxy处理=>$ch){ $status=(int)curl\u getinfo($ch,CURLINFO\u HTTP\u代码); //巨大成功 如果($status>=200&$status<300){ self::$valid[$proxy]=true; $proxy[]=$proxy; } 否则{ self::$valid[$proxy]=false; } //清理单个句柄 卷曲多个拆卸手柄($mh,$ch); } //清理多个句柄 卷曲多重闭合($mh); 返回$this->proxies=$proxies; } 公共函数validate2($useCache=true){ $proxies=array(); foreach($this->代理为$proxy){ //使用缓存和代理已经存在?跳过剩下的废话 如果($useCache&&!empty(self::$valid[$proxy])){ $proxy[]=$proxy; 继续; } 列表($host,$post)=分解(“:”,$proxy); if($conn=@fsockopen($host,$post,$errno,$error,self::TIMEOUT)){ self::$valid[$proxy]=true; $proxy[]=$proxy; fclose($康涅狄格州); }否则{ self::$valid[$proxy]=false; } } 返回$this->proxies=$proxies; } } 到目前为止,我更喜欢
cURL
方法,因为它允许我并行检查大量代理,速度非常快,而不是像
fsockopen
那样一次检查一个代理


我没有对代理做太多的工作,因此我很难判断这些方法是否足以验证代理是否可用,或者是否有更好的方法我缺少。

Hm。尝试通过代理建立到安全(最可能可用)URL的连接,并检查错误,听起来不错


为了获得绝对最大的安全性,您可能希望向另一个验证URL添加另一个调用(例如,Google上的某个东西),或者进行两次调用,以防万一

cURL是首选的方式,因为它有多重执行功能

我不会费心做两次检查,但要立即打谷歌(或代理法官)电话。 代理有时可以允许套接字,但不能获取任何东西:因此您的cURL方法是安全的,不会太慢

正如佩卡上面提到的:这取决于预期用途

你是否使用了Charon并收集了大量代理,我想让他们对照ProxyJudger进行检查,我想知道周转时间(以避免缓慢的代理)和速度

如果您想将它用作公司代理的监控系统,我只想确保它能够获取一个页面

通过使用cURL获取URL来检查代理的(混乱的)示例

TLDR:使用cURL,它可以处理并行请求,并且是最稳定的,不会变慢(通过不执行双重检查)。

第二次可用性检查听起来是个好主意,但请求越多,性能就越令人担忧。没错。我想这取决于预期用途。