Java 你能解释一下HttpURLConnection过程吗?

Java 你能解释一下HttpURLConnection过程吗?,java,inputstream,httpurlconnection,outputstream,urlconnection,Java,Inputstream,Httpurlconnection,Outputstream,Urlconnection,我正在使用HTTPURLConnection连接到web服务。我知道如何使用HTTPURLConnection,但我想了解它是如何工作的。基本上,我想知道以下几点: HTTPURLConnection在哪一点尝试建立到给定URL的连接 在哪一点上我可以知道我能够成功建立连接 是否在一个步骤/方法调用中建立连接并发送实际请求?这是什么方法 你能用外行的术语解释一下getOutputStream和getInputStream的功能吗?我注意到,当我试图连接的服务器关闭时,我在getOutputSt

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

  • HTTPURLConnection
    在哪一点尝试建立到给定URL的连接
  • 在哪一点上我可以知道我能够成功建立连接
  • 是否在一个步骤/方法调用中建立连接并发送实际请求?这是什么方法
  • 你能用外行的术语解释一下
    getOutputStream
    getInputStream
    的功能吗?我注意到,当我试图连接的服务器关闭时,我在
    getOutputStream
    处得到一个
    异常。这是否意味着
    HTTPURLConnection
    只有在调用
    getOutputStream
    时才会开始建立连接?如何使用
    getInputStream
    ?既然我只能在
    getInputStream
    上获得响应,那么这是否意味着我还没有在
    getOutputStream
    上发送任何请求,只是建立了一个连接?调用
    getInputStream
    时,是否返回服务器请求响应
  • 我说的
    openConnection
    只是创建了一个新的连接对象,但还没有建立任何连接,对吗
  • 如何测量读取开销和连接开销
在上面的示例HTTP帖子中,每个方法旁边的前3个问题答案都列为内联注释

发件人:

返回写入此连接的输出流

基本上,我认为你已经很好地理解了这是如何工作的,所以让我用外行的话重申一下
getOutputStream
基本上打开一个连接流,目的是将数据写入服务器。在上面的代码示例中,“message”可以是我们发送到服务器的注释,它表示帖子上留下的注释。当您看到
getOutputStream
时,您正在打开连接流进行写入,但在调用
writer.write(“message=“+message”)之前,您实际上不会写入任何数据

发件人:

返回从该打开连接读取的输入流。如果读取超时在数据可供读取之前过期,则从返回的输入流读取时会引发SocketTimeoutException

getInputStream
的作用正好相反。与
getOutputStream
类似,它也会打开一个连接流,但目的是从服务器读取数据,而不是写入数据。如果连接或流打开失败,您将看到一个
SocketTimeoutException

getInputStream怎么样?既然我只能在getInputStream上获得响应,那么这是否意味着我还没有在getOutputStream上发送任何请求,只是建立了一个连接

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

用外行的话说,发出
getInputStream
请求相当于打电话到你朋友家说“嘿,我可以过来借那副虎钳吗?”然后你的朋友通过说“当然!来拿它”来建立握手。然后,在这一点上,建立了连接,你走到你朋友的家,敲门,请求虎钳,然后走回你的家

对于
getOutputStream
使用类似的例子,可能需要给你的朋友打电话,说“嘿,我欠你的钱在我这里,我可以把它寄给你吗?”?你的朋友需要钱,而且你在里面病得很厉害,所以你把钱藏了这么久,他说:“当然,来吧,你这个卑鄙的混蛋。”。所以你走到你朋友家,把钱“邮寄”给他。然后他把你踢出去,你走回你的房子

现在,继续外行的例子,让我们看看一些例外。如果你打电话给你的朋友,他不在家,那可能是500个错误。如果你打电话,因为你的朋友厌倦了你一直借钱而收到一条断开连接的电话信息,那就是找不到404页。如果你的手机因为没有付账单而死机,那可能是个例外。(注意:本节可能不是100%正确。它旨在让您从外行的角度大致了解正在发生的事情。)

问题#5:

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

openConnection
创建一个新的连接对象。从:

每次通过为此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) );
我确信有更先进的方法来测量请求时间和开销,但这通常足以满足我的需要


有关关闭连接的信息,请参阅。

蒂姆·布雷(Tim Bray)提供了一个简明的分步说明,说明t
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) );
    /* Create a connection LOCAL object,
     * the openConnection() function DOES NOT initiate
     * any packet exchange with the remote server.
     * 
     * The configurations only setup the LOCAL
     * connection object properties.
     */
    HttpURLConnection connection = (HttpURLConnection) dst.openConnection();
    connection.setDoOutput(true);
    connection.setRequestMethod("POST");
    ...//headers setup
    byte[] testContent = {0x32, 0x32};

    /**
     * This triggers packet exchange with the remote
     * server to create a link. But writing/flushing
     * to a output stream does not send out any data.
     * 
     * Payload are buffered locally.
     */
    try (BufferedOutputStream outputStream = new BufferedOutputStream(connection.getOutputStream())) {
        outputStream.write(testContent);
        outputStream.flush();
    }

    /**
     * Trigger payload sending to the server.
     * Client get ALL responses (including response code,
     * message, and content payload) 
     */
    int responseCode = connection.getResponseCode();
    System.out.println(responseCode);

    /* Here no further exchange happens with remote server, since
     * the input stream content has already been buffered
     * in previous step
     */
    try (InputStream is = connection.getInputStream()) {
        Scanner scanner = new Scanner(is);
        StringBuilder stringBuilder = new StringBuilder();
        while (scanner.hasNextLine()) {
        stringBuilder.append(scanner.nextLine()).append(System.lineSeparator());
        }
    }

    /**
     * Trigger the disconnection from the server.
     */
    String responsemsg = connection.getResponseMessage();
    System.out.println(responsemsg);
    connection.disconnect();