HttpURLConnection implementation

我已经读到HttpURLConnection支持持久连接,因此一个连接可以重用于多个请求。我尝试了一下,发送第二个POST的唯一方法是第二次调用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验证了它),但我不明白为什么(尽管这是我想要的),因为我已经调用了断开连接。我检查了HttpURLConnection的源代码,并且该实现确实保留了与相同目标的连接的保持活动缓存。我的问题是,在我发送第一个请求后,我无法看到连接是如何放回缓存中的。断开连接关闭连接,如果没有断开连接,我仍然无法看到连接如何放回缓存中。我看到缓存有一个运行方法可以遍历所有空闲连接(我不确定它是如何调用的),但我找不到如何将连接放回缓存中。似乎唯一发生的地方是在httpClient的完成方法中,但对于带有响应的POST,这不需要。任何人都可以帮我吗?

编辑我感兴趣的是,如何正确处理HttpUrlConnection对象以进行tcp连接重用。是否应该关闭输入/输出流,后跟 url.openConnection();每次发送新请求(避免断开连接())?如果是,当我第二次调用url.openConnection()时,我无法看到连接是如何被重用的,因为连接已从第一个请求的缓存中删除,并且找不到它是如何返回的。是否有可能连接没有返回到保持活动缓存(错误?),但操作系统尚未释放tcp连接,并且在新连接上,操作系统返回缓冲连接(尚未释放)或类似的东西?编辑2我发现的唯一相关内容来自JDK_KeepAlive

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

但我不确定这是哪个处理程序。sun.net.www.protocol.http.handler 不做任何缓存,因为我看到谢谢!


答案 1

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

是的。

如果是,当我第二次调用url.openConnection()时,我无法看到连接是如何被重用的,因为连接已从第一个请求的缓存中删除,并且找不到它是如何返回的。

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


答案 2

来自httpURLConnection的javadoc(我的强调):

每个 HttpURLConnection 实例都用于发出单个请求,但与 HTTP 服务器的底层网络连接可以由其他实例透明地共享。在请求后调用 HttpURLConnection 的 InputStream 或 OutputStream 上的 close() 方法可能会释放与此实例关联的网络资源,但对任何共享的持久连接都没有影响。调用 disconnect() 方法可能会关闭底层套接字,如果持久性连接当时处于空闲状态。


推荐