Lors de l'utilisation de HttpURLConnection, InputStream doit-il être fermé si nous ne le récupérons pas et ne l'utilisons pas?
c'est-à-dire est-ce sûr?
HttpURLConnection conn = (HttpURLConnection) uri.getURI().toURL().openConnection();
conn.connect();
// check for content type I don't care about
if (conn.getContentType.equals("image/gif") return;
// get stream and read from it
InputStream is = conn.getInputStream();
try {
// read from is
} finally {
is.close();
}
Deuxièmement, est-il sûr de fermer un InputStream avant que tout son contenu ne soit entièrement lu ?
Existe-t-il un risque de laisser le socket sous-jacent dans l'état ESTABLISHED ou même CLOSE_WAIT?
est-il sûr de fermer un InputStream avant que tout son contenu ait été lu
Vous devez lire toutes les données dans le flux d'entrée avant de le fermer afin que la connexion sous-jacente TCP soit mise en cache. J'ai lu que cela ne devrait pas être requis dans le dernier Java, mais c'était toujours mandaté pour lire la réponse entière pour la réutilisation de connexion.
Vérifiez cet article: garder en vie dans Java6
Selon http://docs.Oracle.com/javase/6/docs/technotes/guides/net/http-keepalive.html et le code source d'OpenJDK.
(Lorsque keepAlive == true
)
Si le client a appelé HttpURLConnection.getInputSteam().close()
, l'appel ultérieur à HttpURLConnection.disconnect()
ne fermera pas le Socket
. c'est-à-dire que le Socket
est réutilisé (mis en cache)
Si le client n'appelle pas close()
, appelez disconnect()
fermera le InputStream
et fermera le Socket
.
Donc, pour réutiliser le Socket
, il suffit d'appeler InputStream.close()
. N'appelez pas HttpURLConnection.disconnect()
.
Voici quelques informations concernant le cache keep-alive. Toutes ces informations concernent Java 6, mais sont probablement également exactes pour de nombreuses versions antérieures et ultérieures.
D'après ce que je peux dire, le code se résume à:
Cette logique est divisée en deux endroits: autour de la ligne 725 de Sun.net.www.http.HttpClient (dans la méthode "parseHTTPHeader"), et autour de la ligne 120 de Sun.net. www.http.KeepAliveCache (dans la méthode "put").
Il existe donc deux façons de contrôler le délai d'expiration:
On pourrait penser qu'il serait possible de modifier la valeur par défaut de cinq secondes apparemment arbitraire sans recompiler les classes JDK internes, mais ce n'est pas le cas. Un bug a été déposé en 2005 demandant cette capacité, mais Sun a refusé de la fournir.
Si vous voulez vraiment vous assurer que la connexion est fermée, vous devez appeler conn.disconnect()
.
Les connexions ouvertes que vous avez observées sont dues à la fonctionnalité de maintien de la connexion HTTP 1.1 (également connue sous le nom de Connexions persistantes HTTP ). Si le serveur prend en charge HTTP 1.1 et n'envoie pas de Connection: close
dans l'en-tête de réponse Java ne ferme pas immédiatement la connexion sous-jacente TCP lorsque vous fermez le flux d'entrée. Au lieu de cela, il le maintient ouvert et essaie de le réutiliser) pour la prochaine requête HTTP au même serveur.
Si vous ne voulez pas du tout ce comportement, vous pouvez définir la propriété système http.keepAlive
à faux:
System.setProperty("http.keepAlive","false");
Vous devez également fermer le flux d'erreurs si la demande HTTP échoue (tout sauf 200):
try {
...
}
catch (IOException e) {
connection.getErrorStream().close();
}
Si vous ne le faites pas, toutes les requêtes qui ne renvoient pas 200 (par exemple timeout) feront fuir un socket.
Lors de l'utilisation de HttpURLConnection, InputStream doit-il être fermé si nous ne le récupérons pas et ne l'utilisons pas?
Oui, il doit toujours être fermé.
c'est-à-dire est-ce sûr?
Pas à 100%, vous courez le risque d'obtenir un NPE. Plus sûr est:
InputStream is = null;
try {
is = conn.getInputStream()
// read from is
} finally {
if (is != null) {
is.close();
}
}