Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/321.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Network programming HttpURLConnection实现_Network Programming_Java_Jdk1.6_Httpurlconnection - Fatal编程技术网

Network programming HttpURLConnection实现

Network programming HttpURLConnection实现,network-programming,java,jdk1.6,httpurlconnection,Network Programming,Java,Jdk1.6,Httpurlconnection,我已经读到HttpURLConnection支持持久连接,因此一个连接可以被多个请求重用。我试过了,发送第二封邮件的唯一方法就是再次调用openConnection。否则我会得到一个非法的州例外(“已连接”); 我使用了以下方法: try{ URL url = new URL("http://someconection.com"); } catch(Exception e){} HttpURLConnection con = (HttpURLConnection) url.openConnect

我已经读到HttpURLConnection支持持久连接,因此一个连接可以被多个请求重用。我试过了,发送第二封邮件的唯一方法就是再次调用openConnection。否则我会得到一个非法的州例外(“已连接”); 我使用了以下方法:

try{
URL url = new URL("http://someconection.com");
}
catch(Exception e){}
HttpURLConnection con = (HttpURLConnection) url.openConnection();
//set output, input etc
//send POST
//Receive response
//Read whole response
//close input stream
con.disconnect();//have also tested commenting this out
con = (HttpURLConnection) url.openConnection();
//Send new POST
第二个请求是通过相同的TCP连接发送的(用wireshark验证),但我不明白为什么(尽管这是我想要的),因为我调用了disconnect。 我检查了HttpURLConnection的源代码,该实现确实保留了到相同目的地的连接的keepalive缓存。我的问题是,在发送第一个请求后,我看不到如何将连接放回缓存中。断开连接会关闭连接,如果没有断开连接,我仍然看不到连接是如何放回缓存的。我看到缓存有一个run方法可以遍历所有空闲连接(我不确定它是如何调用的),但我找不到如何将连接放回缓存中。唯一可能发生的地方是httpClient的finished方法,但是对于带有响应的POST,不会调用它。 有人能帮我吗

编辑 我的兴趣是,对于tcp连接重用来说,HttpUrlConnection对象的正确处理是什么。输入/输出流是否应该在url.openConnection()后关闭;每次发送新请求时(避免断开连接())?如果是,我在第二次调用url.openConnection()时看不到连接是如何被重用的,因为第一次请求时连接已从缓存中删除,并且找不到它是如何返回的。 是否可能连接没有返回到keepalive缓存(bug?),但操作系统尚未释放tcp连接,并且在新连接上,操作系统返回缓冲连接(尚未释放)或类似的内容? EDIT2 我找到的唯一亲属是来自

…当应用程序调用close()时 在由返回的InputStream上 URLConnection.getInputStream()中的 JDK的HTTP协议处理程序将尝试 清理连接,如果 成功后,将连接放入 连接缓存供将来重用 HTTP请求

但我不确定这是哪位处理者。sun.net.www.protocol.http.Handler没有像我看到的那样进行任何缓存
谢谢

来自javadoc for HttpURLConnection(我的重点):

每个HttpURLConnection实例都是 用于发出单个请求,但 与服务器的基础网络连接 HTTP服务器可能是透明的 被其他实例共享。调用 InputStream上的close()方法或 HttpURLConnection的OutputStream 请求后可能会释放网络 与此关联的资源 实例,但对任何 共享持久连接。使命感 disconnect()方法可以关闭 如果持久化 否则,该连接处于空闲状态 时间

应该关闭输入/输出流吗 后跟url.openConnection(); 每次都要发送新请求 (避免断开连接())

如果是,我看不出连接是如何进行的 当我打电话的时候 第二个的url.openConnection() 时间,因为连接已断开 第一次从缓存中删除 请求,但找不到它是怎样的 他回来了


您将
HttpURLConnection
与底层
Socket
及其底层TCP连接混淆。他们不一样。
HttpURLConnection
实例是GC'd,底层的
Socket
被池化,除非调用
disconnect()。

我发现当InputStream关闭时,连接确实被缓存。一旦inputStream关闭,底层连接将被缓冲。HttpURLConnection对象对于进一步的请求是不可用的,因为该对象仍被视为“已连接”,即其布尔连接被设置为true,并且在将连接放回缓冲区后不会被清除。因此,每次都应该为新的POST实例化一个新的HttpUrlConnection,但是如果底层TCP连接没有超时,它将被重用。 所以EJP答案是正确的描述。尽管显式调用disconnect(),但我看到的行为(重用TCP连接)可能是由于操作系统进行的缓存造成的吗?我不知道。我希望知道的人能解释一下。
谢谢。

Hmmh。我可能在这里遗漏了一些东西(因为这是一个老问题),但据我所知,有两种众所周知的方法可以强制关闭底层TCP连接:

  • 强制使用HTTP 1.0(1.1引入了持久连接)——这由HTTP请求行指示
  • 发送值为“close”的“Connection”标头;这也将迫使关闭
如何使用JDK的HttpUrlConnection“强制使用HTTP1.0”

根据对HTTP1.1的支持一节,可以使用java属性http.keepAlive关闭或打开连接(默认为true)。此外,java属性
http.maxConnections
指示每个目标在任何给定时间保持活动状态的最大(并发)连接数


因此,通过将java属性
http.keepAlive
设置为false,“强制使用HTTP1.0”可以一次应用于整个应用程序。

放弃流将导致TCP连接空闲。应该完全读取响应流。我最初忽略的另一件事,也是在这个主题的大多数答案中被忽略的,就是在异常情况下忘记处理错误流。与此类似的代码修复了我的一个应用程序未正确释放资源的问题:

HttpURLConnection connection = (HttpURLConnection)new URL(uri).openConnection();
InputStream stream = null;
BufferedReader reader = null;
try {
        stream = connection.getInputStream();
        reader = new BufferedReader(new InputStreamReader(stream, Charset.forName("UTF-8")));

        // do work on part of the input stream

} catch (IOException e) {

    // read the error stream
    InputStream es = connection.getErrorStream();
    if (es != null) {
        BufferedReader esReader = null;
        esReader = new BufferedReader(new InputStreamReader(es, Charset.forName("UTF-8")));
        while (esReader.ready() && esReader.readLine() != null) {
        }
        if (esReader != null)
            esReader.close();
    }

    // do something with the IOException
} finally {

    // finish reading the input stream if it was not read completely in the try block, then close
    if (reader != null) {
        while (reader.readLine() != null) {
        }
        reader.close();
    }

    // Not sure if this is necessary, closing the buffered reader may close the input stream?
    if (stream != null) {
        stream.close();
    }

    // disconnect
    if (connection != null) {
        connection.disconnect();
    }
}
缓冲读取器并不是绝对必要的,我选择它是因为我的用例需要readi