如何测试 Android HttpURLConnection 是否有效?

How to test if Android HttpURLConnection is valid?

我的应用使用 HttpUrlConnection() 定期从服务器下载文件。下面是简短的代码示例:

HttpURLConnection conn;
url = new URL( "http://google.com/index.html" );
conn = url.openConnection();         // returns non-null
int rcode = conn.getResponseCode():  // returns 200
// get input stream, read from it and process bytes read

这很好用。但是,如果我替换为伪造的 URL,例如

url=new URL("http://BOGUS-SITE.com/index.html";    

它仍然连接正常,getResponseCode() returns 响应代码 200。输入流 reader returns -1 字节读取。好的,就这样吧。 (有趣的是,如果 URL 的文件名部分是假的,我 do 会得到一个 File-Not-Found 异常。

但是,在我实际尝试读取它之前,如何检测到连接不良(例如,到不存在的主机)?也许那是不可能的?

我想我可以解析 URL 并尝试解析站点名称或对其执行 ping 操作,但这似乎是一个 hack。

更完整的代码摘录:

// Download a file by its URL
    public static int
    doDownload(
      String fileurl)   // file url, e.g. "http:google.com/index.html"
    {
        // NOTE: 'log()' is a wrapper for 'Log.i()'
        int BUFSIZE=10000;
        HttpURLConnection hconn;
        int rcode,nr,nrtot=0;
        InputStream is;
        BufferedInputStream bis;
        byte[] buf;
        URL url;

        try {
            url = new URL( fileurl );                       // form URL
            hconn = (HttpURLConnection)url.openConnection();    // open connection
            log( "Opened connection to \""+fileurl+"\"" );
            rcode = hconn.getResponseCode();                   // get response code
            log("Read HTTP response code: " + rcode);
            is  = hconn.getInputStream();
            bis = new BufferedInputStream( is );                // get buffered stream to read
            buf = new byte[BUFSIZE];
            while( true ) {                                     // read loop
             nr = bis.read( buf, 0, BUFSIZE );             // read some bytes
             if( nr <= 0 ) break;                              // break read loop on EOF
             nrtot += nr;                                      // update total read count
            }
        }
        catch( Exception e ) {
          return( -1 );                                         // rtn ERROR
        }
        return( nrtot );                                        // return num bytes read
    }

更新

我做了一些进一步的调查。我发现为什么有时会返回响应代码 200 而有时会发生 UnknownHostException:这取决于指定的特定“坏”url 主机。例如,如果我指定

我现在正在尝试其他“坏”URLs 来尝试查看模式。

我发现了问题,这是一个 DNS 问题。我发现我的 AT&T phone 正在使用“sbcglobal.net”(AT&T 的默认 DNS 服务器)的 DNS 服务。该 DNS 服务器 returns 一个 IP 地址,即使是 不存在的 名称。特别是,它 returns 属于“akamaitechnologies.com”(无论是什么)的地址。由于 是一个现有站点 ,http 连接并且 getResponseCode returns 200。由于它无法提供我请求的文件,因此下载失败。我认为这是为 akamaitechnologies 产生流量的营销噱头。

当我将 phone 设置为使用“dns.google”(8.8.8.8) 的 DNS 时,一切正常。

这种类型的 DNS 欺骗是一件坏事,因为许多应用依赖于未知主机异常来检测输入不正确的域名,例如在电子邮件地址中。