你能解释一下HttpURLConnection连接过程吗?

Arc*_*rci 131 java inputstream outputstream urlconnection httpurlconnection

HTTPURLConnection用来连接到Web服务.我知道如何使用,HTTPURLConnection但我想了解它是如何工作的.基本上,我想知道以下内容:

  • 在哪一点上HTTPURLConnection尝试建立与给定URL的连接?
  • 在哪一点上我可以知道我能够成功建立连接?
  • 是建立连接并在一步/方法调用中发送实际请求?它是什么方法?
  • 你能解释的功能getOutputStreamgetInputStream外行的任期?我注意到,当我试图连接到服务器宕机,我得到ExceptiongetOutputStream.这是否意味着HTTPURLConnection我只会在调用时开始建立连接getOutputStream?怎么样getInputStream?因为我只能得到响应getInputStream,那么这是否意味着我还没有发送任何请求getOutputStream但只是建立连接?HttpURLConnection我调用时是否回到服务器请求响应getInputStream
  • 我是否正确地说,openConnection只是创建一个新的连接对象,但尚未建立任何连接?
  • 如何衡量读取开销和连接开销?

jmo*_*253 181

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) {
    // ...
}
Run Code Online (Sandbox Code Playgroud)

在上面的示例HTTP POST中,您的问题的前3个答案在每个方法旁边列为内联注释.

来自getOutputStream:

返回写入此连接的输出流.

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

来自getInputStream():

返回从此打开的连接读取的输入流.如果读取超时在数据可用于读取之前到期,则在从返回的输入流读取时可以抛出SocketTimeoutException.

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

getInputStream怎么样?因为我只能在getInputStream中获得响应,那么这是否意味着我还没有在getOutputStream发送任何请求但只是建立连接?

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

通俗地说,提出getInputStream请求相当于打电话给你朋友的房子说"嘿,如果我过来借那副副把手,还可以吗?" 和你的朋友说:"当然!来吧,得到它".然后,在那时,连接完成,你走到你朋友家,敲门,请求副把手,然后走回你家.

使用类似的例子getOutputStream将涉及给你的朋友打电话并说"嘿,我有欠你的钱,我可以把它发给你"吗?你的朋友,你需要金钱和生病的内容,你保持这么长时间,说:"当然,来吧你这个廉价的混蛋".所以你走到你朋友的家里并把钱"邮寄"给他.然后他把你踢出去,然后你走回你家.

现在,继续外行的例子,让我们看一些例外.如果你打电话给你的朋友并且他不在家,那可能是500错误.如果您打电话并收到断开连接的号码信息,因为您的朋友已经厌倦了您一直借钱,那就是找不到404页面.如果您的手机因为没有支付账单而死亡,那可能是IOException.(注意:此部分可能不是100%正确.它旨在让您大致了解外行人的条款.)

问题#5:

是的,你是正确的,openConnection只是创建一个新的连接对象,但不建立它.调用getInputStream或getOutputStream时建立连接.

openConnection创建一个新的连接对象.从URL.openConnection javadocs:

每次通过调用此URL的协议处理程序的openConnection方法打开一个新连接.

在调用openConnection时建立连接,并在实例化时调用InputStream,OutputStream或两者.

问题#6:

为了测量开销,我通常在整个连接块周围包含一些非常简单的定时代码,如下所示:

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) );
Run Code Online (Sandbox Code Playgroud)

我确信有更先进的方法来测量请求时间和开销,但这通常足以满足我的需求.

有关关闭连接的信息,您没有询问,请参阅Java中何时关闭URL连接?.

  • 值得注意的是,HttpURLConnection对象似乎只在它需要的位置到达目标URL.在您的示例中,您有输入和输出流,当然在连接打开之前无法执行任何操作.更简单的情况是GET操作,除了初始化连接然后检查响应代码之外,您什么都不做.在这种情况下,直到调用getResponseCode()方法才实际建立连接.否则,这是对连接生命周期的一个很好的解释和探索! (7认同)
  • 你好。谢谢!!!这确实是一个详细的解释,我非常感谢您的回答。如果我正确理解您的答案,如果尚未建立连接,则 getOutputStream 和 getInputStream 都会建立连接。如果我调用 getOutputStream,然后调用 getInputStream,在内部,HTTPURLConnection 将不再在 getInputStream 处重新建立连接,因为我已经能够在 getOutStream 处建立连接?HttpURLConnection 将重用我能够在 getInputStream 中的 getOutputStream 中建立的任何连接。 (2认同)

小智 15

Tim Bray一步一步地说明了openConnection()没有建立实际的连接.相反,在调用getInputStream()或getOutputStream()等方法之前,不会建立实际的HTTP连接.

http://www.tbray.org/ongoing/When/201x/2012/01/17/HttpURLConnection