java - 能解释一下HttpURLConnection的连接过程吗?

标签 java inputstream httpurlconnection outputstream urlconnection

我正在使用 HTTPURLConnection连接到网络服务。我知道如何使用 HTTPURLConnection但我想了解它是如何工作的。基本上,我想知道以下内容:

  • HTTPURLConnection在哪一点上尝试建立到给定 URL 的连接?
  • 在哪一点我可以知道我能够成功建立连接?
  • 是否在一个步骤/方法调用中建立连接并发送实际请求?是什么方法?
  • 你能解释一下getOutputStream的功能吗?和 getInputStream用外行的话?我注意到当我尝试连接的服务器关闭时,我收到 ExceptiongetOutputStream .是否意味着HTTPURLConnection只有在我调用 getOutputStream 时才会开始建立连接? getInputStream怎么样? ?因为我只能在 getInputStream 得到回复,那么这是否意味着我没有在 getOutputStream 发送任何请求?然而,只是建立一个连接?做 HttpURLConnection当我调用 getInputStream 时返回服务器请求响应?
  • 我这样说是否正确 openConnection只是创建一个新的连接对象,但还没有建立任何连接?
  • 如何测量读取开销和连接开销?
  • 最佳答案

    String message = URLEncoder.encode("my message", "UTF-8");
    
    try {
        // instantiate the URL object with the target URL of the resource to
        // request
        URL url = new URL("http://www.example.com/comment");
    
        // instantiate the HttpURLConnection with the URL object - A new
        // connection is opened every time by calling the openConnection
        // method of the protocol handler for this URL.
        // 1. This is the point where the connection is opened.
        HttpURLConnection connection = (HttpURLConnection) url
                .openConnection();
        // set connection output to true
        connection.setDoOutput(true);
        // instead of a GET, we're going to send using method="POST"
        connection.setRequestMethod("POST");
    
        // instantiate OutputStreamWriter using the output stream, returned
        // from getOutputStream, that writes to this connection.
        // 2. This is the point where you'll know if the connection was
        // successfully established. If an I/O error occurs while creating
        // the output stream, you'll see an IOException.
        OutputStreamWriter writer = new OutputStreamWriter(
                connection.getOutputStream());
    
        // write data to the connection. This is data that you are sending
        // to the server
        // 3. No. Sending the data is conducted here. We established the
        // connection with getOutputStream
        writer.write("message=" + message);
    
        // Closes this output stream and releases any system resources
        // associated with this stream. At this point, we've sent all the
        // data. Only the outputStream is closed at this point, not the
        // actual connection
        writer.close();
        // if there is a response code AND that response code is 200 OK, do
        // stuff in the first if block
        if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
            // OK
    
            // otherwise, if any other status code is returned, or no status
            // code is returned, do stuff in the else block
        } else {
            // Server returned HTTP error code.
        }
    } catch (MalformedURLException e) {
        // ...
    } catch (IOException e) {
        // ...
    }
    

    在上面的示例 HTTP POST 中,对您的问题的前 3 个答案作为内嵌注释列出,位于每个方法旁边。

    来自 getOutputStream :

    Returns an output stream that writes to this connection.



    基本上,我认为你对它的工作原理有很好的理解,所以让我用外行的话重申一下。 getOutputStream基本上是打开一个连接流,目的是将数据写入服务器。在上面的代码示例中,“消息”可能是我们发送到服务器的评论,表示在帖子上留下的评论。当你看到getOutputStream ,您正在打开连接流进行写入,但在您调用 writer.write("message=" + message); 之前您实际上并没有写入任何数据.

    来自 getInputStream() :

    Returns an input stream that reads from this open connection. A SocketTimeoutException can be thrown when reading from the returned input stream if the read timeout expires before data is available for read.


    getInputStream反其道而行之。喜欢 getOutputStream ,它还打开一个连接流,但目的是从服务器读取数据,而不是写入数据。如果连接或流打开失败,您将看到 SocketTimeoutException .

    How about the getInputStream? Since I'm only able to get the response at getInputStream, then does it mean that I didn't send any request at getOutputStream yet but simply establishes a connection?



    请记住,发送请求和发送数据是两种不同的操作。当您调用 getOutputStream 或 getInputStream 时 url.openConnection() ,您向服务器发送请求以建立连接。在服务器向您发回已建立连接的确认时,会发生握手。那时您就可以准备发送或接收数据了。因此,您不需要调用 getOutputStream 来建立连接打开流,除非您发出请求的目的是发送数据。

    通俗地说,就是做一个 getInputStream要求相当于打电话到你 friend 家说“嘿,我过来借那副副 Handlebars 可以吗?”你的 friend 通过说“当然!过来拿它”来建立握手。然后,在这一点上,建立连接,你走到你 friend 的房子,敲门,请求副 Handlebars ,然后走回你的房子。

    getOutputStream 使用类似的示例会涉及调用你的 friend 并说“嘿,我欠你的钱,我可以寄给你吗”?你的 friend 需要钱而且病了,你把它藏了这么久,他说:“当然,过来你这个贱货”。所以你走到你 friend 的家里,把钱“邮寄”给他。然后他把你踢出去,你走回自己的房子。

    现在,继续外行的例子,让我们看看一些异常(exception)。如果你调用你的 friend ,但他不在家,那可能是 500 错误。如果您因为 friend 厌倦了您一直在借钱而调用电话并收到一条已断开的号码消息,那就是找不到 404 页面。如果你的手机因为你没有支付账单而死机,那可能是一个 IOException。 (注意:本节可能不是 100% 正确。它的目的是让您大致了解所发生的情况。)

    问题 #5:

    是的,您是正确的 openConnection 只是创建一个新的连接对象,但没有建立它。当您调用 getInputStream 或 getOutputStream 时,就会建立连接。
    openConnection创建一个新的连接对象。来自 URL.openConnection javadocs :

    A new connection is opened every time by calling the openConnection method of the protocol handler for this URL.



    当您调用 openConnection 时建立连接,并且在实例化它们时调用 InputStream、OutputStream 或两者。

    问题 #6 :

    为了测量开销,我通常在整个连接 block 周围包装一些非常简单的计时代码,如下所示:
    long start = System.currentTimeMillis();
    log.info("Time so far = " + new Long(System.currentTimeMillis() - start) );
    
    // run the above example code here
    log.info("Total time to send/receive data = " + new Long(System.currentTimeMillis() - start) );
    

    我确信有更高级的方法来测量请求时间和开销,但这通常足以满足我的需要。

    有关关闭连接的信息,您没有询问,请参阅 In Java when does a URL connection close? .

    关于java - 能解释一下HttpURLConnection的连接过程吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10116961/

    相关文章:

    java - 在类路径 :/cucumberOptions 中找不到任何功能

    java - 如何在 Java 中将 String[] 数组转换为 InputStream

    java - 如何从套接字读取数据并将其写入文件?

    java - 基于 JVM 的 longpoll/comet 客户端 : routers killing idle connections

    java - Spring Integration Kafka消息驱动 channel 适配器接收消息

    java - Hadoop..如何计算输入拆分的散列

    java - 如何使用 JsonReader 从 URL 读取 JSON 对象?

    java - IOException : "Received authentication challenge is null" (Apache Harmony/Android)

    java - 为什么我不断收到 java.net.SocketException : Connection reset error?

    java - Spring 3.0 MVC 绑定(bind)嵌套对象