Muss bei der Verwendung von HttpURLConnection der InputStream geschlossen werden, wenn wir ihn nicht 'bekommen' und verwenden?
ist das sicher?
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();
}
Ist es zweitens sicher, einen InputStream zu schließen, bevor sein gesamter Inhalt vollständig gelesen wurde ?
Besteht die Gefahr, dass der zugrunde liegende Socket im Zustand ESTABLISHED oder sogar CLOSE_WAIT belassen wird?
ist es sicher, einen InputStream zu schließen, bevor sein gesamter Inhalt gelesen wurde?
Sie müssen alle Daten im Eingabestream lesen, bevor Sie ihn schließen, damit die zugrunde liegende TCP) - Verbindung zwischengespeichert wird. Ich habe gelesen, dass sie im neuesten Java nicht erforderlich sein sollte, aber es war Immer beauftragt, die gesamte Antwort für die Wiederverwendung der Verbindung zu lesen.
Überprüfen Sie diesen Beitrag: Keep-Alive in Java6
Laut http://docs.Oracle.com/javase/6/docs/technotes/guides/net/http-keepalive.html und OpenJDK-Quellcode.
(Wenn keepAlive == true
)
Wenn der Client HttpURLConnection.getInputSteam().close()
aufgerufen hat, wird der spätere Aufruf von HttpURLConnection.disconnect()
NICHT schließenSocket
. d.h. das Socket
wird wiederverwendet (zwischengespeichert)
Wenn der Client close()
nicht aufruft, wird durch Aufrufen von disconnect()
das InputStream
und das Socket
geschlossen.
Um das Socket
wiederzuverwenden, rufen Sie einfach InputStream.close()
auf. Rufen Sie HttpURLConnection.disconnect()
nicht auf.
Hier finden Sie einige Informationen zum Keep-Alive-Cache. Alle diese Informationen beziehen sich auf Java 6, sind aber wahrscheinlich auch für viele frühere und spätere Versionen zutreffend.
Soweit ich das beurteilen kann, läuft der Code auf Folgendes hinaus:
Diese Logik ist auf zwei Stellen aufgeteilt: um die Zeile 725 von Sun.net.www.http.HttpClient (in der Methode "parseHTTPHeader") und um die Zeile 120 von Sun.net. www.http.KeepAliveCache (in der "put" -Methode).
Es gibt also zwei Möglichkeiten, den Timeout-Zeitraum zu steuern:
Man könnte meinen, dass es möglich wäre, den scheinbar willkürlichen Fünf-Sekunden-Standard zu ändern, ohne interne JDK-Klassen neu zu kompilieren, aber das ist es nicht. Ein Bug wurde 2005 eingereicht, um diese Fähigkeit anzufordern, aber Sun weigerte sich, sie bereitzustellen.
Wenn Sie wirklich sicherstellen möchten, dass die Verbindung geschlossen ist, sollten Sie conn.disconnect()
aufrufen.
Die von Ihnen beobachteten offenen Verbindungen sind auf die Funktion zum Aufrechterhalten der HTTP 1.1-Verbindung zurückzuführen (auch bekannt als HTTP Persistent Connections ). Wenn der Server HTTP 1.1 unterstützt und kein Connection: close
Im Antwortheader sendet, wird Java die zugrunde liegende TCP Verbindung nicht sofort geschlossen, wenn Sie den Eingabestream schließen. Stattdessen wird es geöffnet und versucht, es für die nächste HTTP-Anforderung an denselben Server erneut zu verwenden.
Wenn Sie dieses Verhalten überhaupt nicht möchten, können Sie die Systemeigenschaft http.keepAlive
Auf false setzen:
System.setProperty("http.keepAlive","false");
Sie müssen den Fehlerstrom auch schließen, wenn die HTTP-Anforderung fehlschlägt (alles andere als 200):
try {
...
}
catch (IOException e) {
connection.getErrorStream().close();
}
Wenn Sie dies nicht tun, verlieren alle Anforderungen, die nicht 200 zurückgeben (z. B. Zeitüberschreitung), einen Socket.
Muss bei der Verwendung von HttpURLConnection der InputStream geschlossen werden, wenn wir ihn nicht 'bekommen' und verwenden?
Ja, es muss immer geschlossen sein.
ist das sicher?
Nicht 100%, Sie laufen Gefahr, eine NPE zu bekommen. Sicherer ist:
InputStream is = null;
try {
is = conn.getInputStream()
// read from is
} finally {
if (is != null) {
is.close();
}
}