URL.openconnection()被调用时做了什么?

9

我希望知道在URL.openconnection()时发生了什么。
我进行了一些类似如下的测试:

public static void main(String[] args) {
    //    testConnection("http://www.google.com");
    testConnection("http://219.09.34.23.1");
}

private static void testConnection(final String _url) {
    new Thread(new Runnable() {
        String strurl = _url;
        long starttime = 0;
        long endtime = 0;

        public void run() {
            try {
                System.out.println("open:" + strurl);

                starttime = System.currentTimeMillis();
                System.out.println("starttime:" + starttime);

                URL url = new URL(strurl);
                HttpURLConnection conn = (HttpURLConnection) url
                        .openConnection();

                endtime = System.currentTimeMillis();
                System.out.println("openConnection endtime:" + endtime);
                System.out
                        .println("spend:" + (endtime - starttime) + " ms");

                conn.connect();
                endtime = System.currentTimeMillis();
                System.out.println("connect endtime2:" + endtime);
                System.out
                        .println("spend:" + (endtime - starttime) + " ms");

                conn.getResponseCode();
                endtime = System.currentTimeMillis();
                System.out.println("endtime3:" + endtime);
                System.out
                        .println("spend:" + (endtime - starttime) + " ms");
            } catch (MalformedURLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();

                endtime = System.currentTimeMillis();
                System.out.println("MalformedURLException endtime:"
                        + endtime);
                System.out
                        .println("spend:" + (endtime - starttime) + " ms");
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();

                endtime = System.currentTimeMillis();
                System.out.println(" IOException endtime:" + endtime);
                System.out
                        .println("spend:" + (endtime - starttime) + " ms");
            }

        }
    }).start();
}

当我运行testConnection("http://www.google.com")时,一切都正常。
当我运行testConnection("http://219.09.34.23.1")时,“219.09.34.23.1”是一个随机的IP地址,有可能不存在,它会打印出以下内容:

open:http://219.09.34.23.1
starttime:1338978920350
openconnection endtime:1338978920355
spend:5 ms

    java.net.UnknownHostException: 219.09.34.23.1  
    at java.net.PlainSocketImpl.connect(Unknown Source)  
    at java.net.SocksSocketImpl.connect(Unknown Source)  
    at java.net.Socket.connect(Unknown Source)  
    at java.net.Socket.connect(Unknown Source)  
    at sun.net.NetworkClient.doConnect(Unknown Source)  
    at sun.net.www.http.HttpClient.openServer(Unknown Source)  
    at sun.net.www.http.HttpClient.openServer(Unknown Source)  
    at sun.net.www.http.HttpClient.<init>(Unknown Source)  
    at sun.net.www.http.HttpClient.New(Unknown Source)  
    at sun.net.www.http.HttpClient.New(Unknown Source)  
    at sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(Unknown Source)  
    at sun.net.www.protocol.http.HttpURLConnection.plainConnect(Unknown Source)  
    at sun.net.www.protocol.http.HttpURLConnection.connect(Unknown Source)  
    at Main$1.run(Main.java:37)  
    at java.lang.Thread.run(Unknown Source)

IOException endtime:1338978920393
spend:43 ms

这意味着运行openconnection花费了5毫秒的时间,而在查找它是未知主机时花费了43毫秒。我的问题是,当URL.openconnection()作为“219.09.34.23.1”时被视为未知主机时,到底发生了什么?


1
像什么?你的意图是什么?请编辑成一个真正的问题。 - timaschew
2个回答

11
如果你阅读 URL.openConnection() 的 javadocs,你会发现:

返回一个表示到 URL 引用的远程对象的连接的 URLConnection 实例。

每次调用该 URL 的协议处理程序的 URLStreamHandler.openConnection(URL) 方法时, 都会创建一个新的 URLConnection 实例。

需要注意的是,在创建时 URLConnection 实例并不会建立实际的网络连接。 只有在调用 URLConnection.connect() 时才会建立连接。

更新:

你在 "random ip" 中使用的 IP 不合法;它应该由 4 个八位组成,而不是 5 个。43ms 可能是用于:(1) 对非 IP 地址进行 DNS 查找 (2) 打印堆栈跟踪。


我已经看过那份文档,另一个问题是在哪种情况下会抛出IOException异常,因为方法(URL.openconnection)的声明中只有在调用URLConnection.connect()时才会建立实际的网络连接。 - Yunfei Tang
@YunfeiTang 在URL无法解析的情况下,例如。 - user207421

10

打开连接不同于连接

openconnection并不能让你下载URL内容,这是肯定的。你需要调用connect。但实际上,下面的内容会解释:

你并不总是需要显式地调用connect方法来初始化连接。依赖于连接的操作,比如getInputStreamgetOutputStream等,如果必要的话,会隐式地执行连接。


2
哇,我已经寻找这个答案有一段时间了。我没有找到任何文档说connect()可以被隐式调用,但这确实符合URLConnection的行为。 - Jade
Benjamin,如果你认为现在的答案是正确的,请把你的反对投票改成赞成投票,好吗? - hasan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接