HttpURLConnection Umsetzung
-
27-09-2019 - |
Frage
Ich habe gelesen, dass HttpURLConnection unterstützt persistente Verbindungen, so dass eine Verbindung für mehrere Anfragen wiederverwendet werden kann. Ich versuchte es, und der einzige Weg, um eine zweite POST war zu senden, indem openconnection ein zweites Mal aufgerufen wird. Ansonsten habe ich eine Illegal ( „Bereits verbunden“); Früher habe ich die folgenden:
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
Die zweite Anforderung wird über die gleiche TCP-Verbindung senden (überprüfte es mit wireshark), aber ich kann nicht verstehen, warum (wenn auch das ist, was ich will), da ich disconnect genannt habe. Ich überprüfte den Quellcode für die HttpURLConnection und die Umsetzung hat die gleichen Ziele eine Keep-Alive-Cache von Verbindungen zu halten. Mein Problem ist, dass ich nicht sehen kann, wie die Verbindung im Cache platziert zurück, nachdem ich die erste Anfrage schicken. Der Trenn schließt die Verbindung und ohne Trenn, noch kann ich nicht sehen, wie die Verbindung im Cache platziert zurück. Ich sah, dass der Cache-Speicher eine run-Methode hat über alle Verbindungen im Leerlauf zu durchlaufen (ich bin nicht sicher, wie es genannt wird), aber ich kann nicht finden, wie die Verbindung wieder in dem Cache gelegt wird. Der einzige Ort, die zu geschehen scheint, ist in der fertigen Methode des Httpclient dies ist jedoch nicht für eine POST mit einer Antwort genannt. Kann mir jemand helfen auf das?
Bearbeiten Mein Interesse ist, was ist die richtige Handhabung eines HttpURLConnection Objekt für TCP-Verbindung Wiederverwendung. Should Eingangs- / Ausgangsstrom geschlossen, gefolgt von einer url.openConnection (); jedes Mal die neue Anforderung (Vermeidung von disconnect ()) senden? Wenn ja, kann ich nicht sehen, wie die Verbindung wiederverwendet wird, wenn ich rufe url.openConnection () zum zweiten Mal, da die Verbindung aus dem Cache für die erste Anforderung entfernt wurde und nicht finden kann, wie es wieder zurückgeführt wird. Ist es möglich, dass die Verbindung nicht zurück in den Keep-Alive-Cache (Bug?) Zurückgegeben wird, aber das Betriebssystem nicht freigegeben hat die TCP-Verbindung noch und auf neue Verbindung, die OS liefern die gepufferte Verbindung (noch nicht erschienen) oder etwas ähnliches? EDIT2 Der einzige Zusammenhang fand ich war von JDK_KeepAlive
... wenn die Anwendung ruft close () auf der Inputzurück durch URLConnection.getInputStream (), der JDK HTTP-Protokoll-Handler wird versuchen, die Verbindung zu bereinigen, und wenn erfolgreich, stellen Sie die Verbindung in ein Verbindungscache für die Wiederverwendung von Zukunft HTTP-Anfragen.
Aber ich bin nicht sicher, welche Handler dieser ist. sun.net.www.protocol.http.Handler führt keine Zwischenspeicherung als ich sah, Dank!
Lösung
Should Eingangs- / Ausgangsstrom geschlossen werden gefolgt von einer url.openConnection (); jedes Mal die neue Anfrage senden (Vermeidung von disconnect ())?
Ja.
Wenn ja, kann ich nicht sehen, wie die Verbindung zu sein, ist wenn ich wiederverwendet nennen url.openConnection () für das zweite Zeit, da die Verbindung wurde aus dem Cache-Speicher für die ersten entfernt fordern und nicht finden kann, wie es ist kehrte zurück.
Sie sind verwirrend die HttpURLConnection
mit der darunterliegenden Socket
und seiner zugrunde liegenden TCP-Verbindung. Sie sind nicht das gleiche. Die HttpURLConnection
Instanzen sind GC'd, wird die zugrunde liegende Socket
gepoolt, es sei denn, Sie rufen disconnect().
Andere Tipps
Von der javadoc für HttpURLConnection (Hervorhebung von mir):
Jede HttpURLConnection Instanz verwendet, um eine einzelne Anfrage zu machen, aber die zugrunde liegende Netzwerkverbindung zum HTTP-Server kann transparent sein geteilt durch andere Instanzen. Der Aufruf der close () Verfahren auf der Inputstream oder Output eines HttpURLConnection nach einer Anfrage kann Netzwerk frei Ressourcen, die damit verbunden Instanz hat aber keinen Einfluss auf irgend geteilt dauerhafte Verbindung. Berufung die disconnect () Methode können in der Nähe der zugrundeliegenden Buchse, wenn eine persistente Verbindung ist nicht anderweitig genutzt an, dass Zeit.
Ich fand, dass die Verbindung tatsächlich zwischengespeichert wird, wenn die Input geschlossen ist. Sobald der input geschlossen wurde, wird die zugrunde liegende Verbindung gepuffert. Das HttpURLConnection Objekt ist unbrauchbar für weitere Anfragen obwohl, da das Objekt immer noch als „verbunden“ ist, das heißt seine boolean verbunden wird auf wahr gesetzt und wird nicht gelöscht, sobald die Verbindung wieder in dem Puffer platziert wird. Also jedes Mal, soll eine neue HttpURLConnection für einen neuen POST instanziert werden, aber die zugrunde liegende TCP-Verbindung wird wiederverwendet werden, wenn es nicht abgelaufen ist. So EJP Antwort der war die richtige Beschreibung. Kann das Verhalten, das ich sehe sein (Wiederverwendung der TCP-Verbindung) trotz ausdrücklich disconnect () aufgerufen wurde durch Caching von dem O getan? Ich weiß nicht. Ich hoffe, jemand, der erklären kann, weiß. Danke.
Wie kann man "Kraft Verwendung von HTTP1.0" mit der HttpURLConnection von JDK?
Nach dem Abschnitt „Persistent Connections“ die Java 1.5 Führung Unterstützung für HTTP1.1 können Verbindungen der Java-Eigenschaft http.keepAlive
ausgeschaltet werden oder über die Verwendung (Standard ist true). Darüber hinaus zeigt die Java-Eigenschaft http.maxConnections
die maximale Anzahl von (gleichzeitige) Verbindungen pro Ziel zu einem bestimmten Zeitpunkt am Leben gehalten werden.
Daher ist eine „Kraft Verwendung von HTTP1.0“ für die gesamte Anwendung angewendet werden kann auf einmal durch die Java-Eigenschaft http.keepAlive
auf false setzen.
hmmh. Ich kann hier etwas fehle (da dies eine alte Frage ist), aber soweit ich weiß, gibt es 2 bekannte Weisen Schließen der zugrunde liegenden TCP-Verbindung zu erzwingen:
- Kraft Verwendung von HTTP 1.0 (1.1 eingeführt persistenten Verbindungen) - dies, wie durch die HTTP-Anforderung Linie angezeigt
- Senden ‚Verbindung‘ Header mit dem Wert ‚schließen‘; dies schließt auch erzwingen.
Der Verzicht auf Ströme werden inaktive TCP-Verbindungen verursachen. Der Antwortstrom sollte vollständig gelesen werden. Ein andere Sache übersah ich anfangs, und übersehen habe zu diesem Thema in den meisten Antworten gesehen wird vergessen, mit dem Fehlerstrom im Fall von Ausnahmen zu behandeln. Code ähnlich wie dieses Fest einen meiner Anwendungen, die nicht war Ressourcen richtig loslassen:
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();
}
}
Die gepufferte Leser sind nicht unbedingt notwendig, wählte ich es, weil mein Anwendungsfall erforderlich, um eine Zeile zu einem Zeitpunkt zu lesen.
Siehe auch: http: // docs .oracle.com / JavaSE / 1.5.0 / docs / guide / net / http-keepalive.html