2014-07-06 30 views
6
nicht trennen

von netstat auf dem Server ausgeführt wird:
BIS vor wenigen Tagen: Ich konnte die Verbindung sehen ESTABLISHED nur für etwa eine Sekunde zu sein, und dann wäre es aus der Liste verschwinden
JETZT: als ESTABLISHED bleibt etwa 10 Sekunden, dann geht es in FIN_WAIT1 und FIN_WAIT2Android: HttpURLConnection nicht

der Android-Code ist der gleiche, der Server ist immer noch die gleiche

ist es möglich, dass irgendeine Art von Android-Update die Dinge verändert haben könnte?

Ich kann es nicht wirklich erklären.

berichte ich den Code unten. Die urlConnection.disconnect() wird ausgeführt, aber die Verbindung bleibt auf dem Server bestehen.

HttpURLConnection urlConnection = null; 
    System.setProperty("http.keepAlive", "false"); 

    try { 
     URL url = new URL(stringUrl); 
     urlConnection = (HttpURLConnection) url.openConnection(); 
     InputStream instream = new BufferedInputStream(urlConnection.getInputStream()); 
     ... 
     instream.close(); 
    } catch (MalformedURLException e) { 
     e.printStackTrace(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } finally { 
     if (urlConnection!=null) { 
      urlConnection.disconnect(); 
     } 
    } 
+0

Versuchen Sie, ziehen Sie das 'Connection' Header' close' einzustellen. – hgoebl

+0

Ich habe das ausprobiert, und anstelle von FIN_WAIT1 und FIN_WAIT2 geht es in TIME_WAIT –

Antwort

1

Gemäß wie das TCP Protokoll funktioniert, wenn Sie eine Verbindung zu schließen, ist es nicht automatisch aus Ihrer Steckdose Liste verschwinden.

Wenn Sie senden Sie das Beendigungssignal an den anderen Teil, dort beginnt ein Protokoll (eine Prozedur, mehr wie), wo der erste Schritt ist genau Ihre Absicht, die Verbindung zu schließen. Sie senden ein Signal an den anderen Knoten und dies würde den Status FIN_WAIT1 beinhalten.

Wenn der Benutzer dieses Signal empfangen hat, ist der nächste Schritt, um es von der entfernten Seite zu bestätigen. Dies bedeutet, dass der gegenüberliegende Server Ihnen ein weiteres Signal sendet, das symbolisiert, dass der Knoten auch bereit ist, die Verbindung zu schließen. Das wäre der FIN_WAIT2 Status.

Zwischen diesen beiden Schritten kann es vorkommen, dass der Remote-Knoten noch nicht geantwortet hat (so dass Sie nicht bestätigt worden ist, dass Sie die Verbindung schließen wollen). In dieser Zeit befinden Sie sich in einem Zwischenzustand mit der Bezeichnung CLOSE_WAIT (Fortsetzen: Sobald Sie das Signal FIN an den Remote-Server gesendet haben und diese noch nicht geantwortet haben).

Der Status TIME_WAIT würde bedeuten, dass Sie dem Server etwas Zeit geben, bevor Sie ihn endgültig schließen, um einige Pakete zu empfangen. Sie tun dies, weil Verbindungsanomalien möglicherweise auftreten und der Remote-Server die Nachricht "Trennung" nicht empfangen und Ihnen ein Paket senden konnte. Wenn das passiert, anstatt einen neuen Socket zwischen den beiden Knoten zu erstellen, verknüpfen Sie ihn mit dem, den Sie im TIME_WAIT-Status haben, und verwerfen Sie einfach dieses Paket, weil die Sequenznummer wahrscheinlich nicht geordnet wird.

Es gibt einige andere Zustände you might see, aber nach der Art, wie Sie es beschreiben, scheint es ziemlich normal zu mir, es sei denn, wenn Sie die .disconnect() Methode aufrufen, würde der ESTABLISHED Status dauern. In diesem Fall funktioniert etwas nicht wie erwartet (es könnte mit einer Art von Überladung oder nicht optimiertem Code zusammenhängen, der Ihre Ausführung sehr langsam machen könnte).

1

dem Moment, wo alle Daten auf den Eingangsstrom verbraucht wird, wird die Verbindung automatisch freigegeben und an den Verbindungspool hinzugefügt. Die zugrunde liegende Socketverbindung wird nicht freigegeben, vorausgesetzt, die Verbindung wird in naher Zukunft wiederverwendet. Es ist eine gute Praxis disconnect in finally Block zu nennen, wie es von Verbindungsfreigabe bei exceptions kümmert.Hier

ist die Implementierung von Leseverfahren von FixedLengthInputStream:

@Override public int read(byte[] buffer, int offset, int count) throws IOException { 
     Arrays.checkOffsetAndCount(buffer.length, offset, count); 
     checkNotClosed(); 
     if (bytesRemaining == 0) { 
      return -1; 
     } 
     int read = in.read(buffer, offset, Math.min(count, bytesRemaining)); 
     if (read == -1) { 
      unexpectedEndOfInput(); // the server didn't supply the promised content length 
      throw new IOException("unexpected end of stream"); 
     } 
     bytesRemaining -= read; 
     cacheWrite(buffer, offset, read); 
     if (bytesRemaining == 0) { 
      endOfInput(true); 
     } 
     return read; 
    } 

Wenn bytesRemaining Variable 0 wird, endOfInput genannt wird, die Rufauslösung Methode mit echten Parameter futher wird, die die Verbindung wird gewährleistet, wird gepoolt.

protected final void endOfInput(boolean reuseSocket) throws IOException { 
    if (cacheRequest != null) { 
      cacheBody.close(); 
    } 
    httpEngine.release(reuseSocket); 
} 

Hier ist die release Methodenimplementierung. Die letzte if-Prüfung stellt sicher, dass die Verbindung geschlossen oder dem Verbindungspool zur Wiederverwendung hinzugefügt werden muss.

public final void release(boolean reusable) { 
    // If the response body comes from the cache, close it. 
    if (responseBodyIn == cachedResponseBody) { 
     IoUtils.closeQuietly(responseBodyIn); 
    } 
    if (!connectionReleased && connection != null) { 
     connectionReleased = true; 
     // We cannot reuse sockets that have incomplete output. 
     if (requestBodyOut != null && !requestBodyOut.closed) { 
      reusable = false; 
     } 
     // If the headers specify that the connection shouldn't be reused, don't reuse it. 
     if (hasConnectionCloseHeader()) { 
      reusable = false; 
     } 
     if (responseBodyIn instanceof UnknownLengthHttpInputStream) { 
      reusable = false; 
     } 
     if (reusable && responseBodyIn != null) { 
      // We must discard the response body before the connection can be reused. 
      try { 
       Streams.skipAll(responseBodyIn); 
      } catch (IOException e) { 
       reusable = false; 
      } 
     } 
     if (!reusable) { 
      connection.closeSocketAndStreams(); 
      connection = null; 
     } else if (automaticallyReleaseConnectionToPool) { 
      HttpConnectionPool.INSTANCE.recycle(connection); 
      connection = null; 
     } 
    } 
} 

Hinweis: Ich Paar vorher beantwortet hatte Fragen von SO zu HttpURLConnection zusammen, die Sie für das Verständnis der zugrunde liegenden Implementierung helfen können. Hier sind die Links: Link1 und Link2.

+0

* wird * endlich {} im Falle einer Exception aufgerufen? –

+0

@ jesses.coktt Ja schließlich Block wird im Ausnahmefall ausgeführt. –

+0

cool thx ... war sicher, aber gut zu wissen. –

0

Sie haben Ihre offene URLConnection

HttpURLConnection urlConnection = null; 
System.setProperty("http.keepAlive", "false"); 

try { 
    URL url = new URL(stringUrl); 
    urlConnection = (HttpURLConnection) url.openConnection(); 
    InputStream instream = new BufferedInputStream(urlConnection.getInputStream()); 
    ... 
    instream.close(); 
    urlConnection.disconnect(); //HERE 
} catch (MalformedURLException e) { 
    e.printStackTrace(); 
} catch (IOException e) { 
    e.printStackTrace(); 
} finally { 
    if (urlConnection!=null) { 
     urlConnection.disconnect(); 
    } 
} 
+0

finally Block wird sowohl im Normal- als auch im Exception-Szenario ausgeführt. Daher ist es nicht notwendig, in try block "disconnect" aufzurufen. –