Domanda

Ho letto che HttpURLConnection supporta connessioni persistenti, in modo che una connessione può essere riutilizzato per richieste multiple. L'ho provato e l'unico modo per inviare un secondo POST era chiamando OpenConnection per la seconda volta. In caso contrario, ho ottenuto un IllegalStateException ( "Già collegata"); Ho usato il seguente:

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

La seconda richiesta è inviare sulla stessa connessione TCP (verificato con wireshark), ma non riesco a capire il motivo per cui (anche se questo è quello che voglio) dato che ho chiamato disconnessione. Ho controllato il codice sorgente per il HttpURLConnection e l'implementazione non mantenere una cache keepalive di connessioni per le stesse destinazioni. Il mio problema è che non riesco a vedere come la connessione viene rimesso nella cache dopo che ho inviare la prima richiesta. La disconnessione chiude la connessione e senza la disconnessione, ancora non riesco a vedere come la connessione viene rimesso nella cache. Ho visto che la cache ha un metodo run di passare attraverso più di tutte le connessioni inattive (non sono sicuro di come viene chiamato), ma non riesco a trovare il modo la connessione viene rimesso nella cache. L'unico posto che sembra accadere è nel metodo finita di HttpClient ma questo non è richiesto un POST con una risposta. Chiunque può aiutare me su questo?

Modifica Il mio interesse è, qual è la corretta manipolazione di un oggetto HttpURLConnection per il riutilizzo connessione TCP. flusso di ingresso / uscita dovrebbero essere chiusi seguito da un url.openConnection (); ogni tempo per inviare la nuova richiesta (evitando di disconnessione ())? Se sì, non riesco a vedere come la connessione viene riutilizzata quando chiamo url.openConnection () per la seconda volta, dal momento che il collegamento è stato rimosso dalla cache per la prima richiesta e non riesce a trovare come si è restituito di nuovo. E 'possibile che la connessione non è restituito di nuovo alla cache keepalive (bug?), Ma il sistema operativo non ha ancora rilasciato la connessione TCP e sulla nuova connessione, il sistema operativo restituisce la connessione tamponata (non ancora rilasciato) o qualcosa di simile? EDIT2 L'scoperto che solo legati era da JDK_KeepAlive

  

... quando l'applicazione chiama close ()   sul InputStream restituito da   URLConnection.getInputStream (), la   gestore di protocollo HTTP del JDK proverà   per ripulire la connessione e, se   successo, mettere il collegamento in un   cache di connessione per il riutilizzo per il futuro   le richieste HTTP.

Ma io non sono sicuro di quale gestore è questo. sun.net.www.protocol.http.Handler non fa alcun caching come ho visto Grazie!

È stato utile?

Soluzione

  

flusso di input / output deve essere chiusa   seguito da un url.openConnection ();   ogni volta per inviare la nuova richiesta   (Evitando di disconnessione ())?

Sì.

  

Se sì, non riesco a vedere come la connessione viene   riutilizzato quando chiamo   url.openConnection () per la seconda   il tempo, dal momento che la connessione è stata   rimosso dalla cache per la prima   richiesta e non può trovare come è   indietro restituito.

Si confondono la HttpURLConnection con la Socket sottostante e la sua sottostante connessione TCP. Essi non sono gli stessi. Le istanze sono HttpURLConnection GC'd, il Socket sottostante è riunito, a meno che non si chiama disconnect().

Altri suggerimenti

Dal Javadoc per HttpURLConnection (il corsivo è mio):

  

Ogni istanza è HttpURLConnection   usato per fare un singola richiesta, ma la   connessione di rete sottostante al   server HTTP può essere trasparente   condiviso da altre istanze. Chiamando il   chiudi metodi () sul InputStream o   OutputStream di un HttpURLConnection   dopo una richiesta può liberare rete   risorse associato a questa   grado, ma non ha alcun effetto su qualunque   condiviso connessione persistente. chiamata   il metodo di disconnessione () possono vicino al   sottostante presa se un persistente   collegamento è inattivo in quel   tempo.

Ho trovato che la connessione è infatti memorizzato nella cache quando l'InputStream è chiusa. Una volta che l'inputStream è stata chiusa la connessione sottostante è tamponata. L'oggetto HttpURLConnection è inutilizzabile per ulteriori richieste però, poiché l'oggetto è considerato ancora "connesso", cioè la sua boolean collegato è impostata su true e non viene cancellata quando la connessione viene reinserito nel buffer. Così ogni volta che un nuovo HttpURLConnection dovrebbe essere un'istanza per un nuovo post, ma la connessione TCP sottostante verrà riutilizzato, se non è scaduto. Così EJP risposta è stata la descrizione corretta. Può essere la sega comportamento che, (riutilizzo della connessione TCP) nonostante abbia chiamato in modo esplicito di disconnessione () è dovuta alla cache fatto dal sistema operativo? Non lo so. Spero che qualcuno che sa può spiegare. Grazie.

  

Come si fa "l'uso di forza HTTP1.0" usando il HttpURLConnection di JDK?

Secondo la sezione “Connessioni persistenti” del 1.5 guida di supporto Java per HTTP1.1 connessioni possono essere spenti o sull'uso del http.keepAlive proprietà Java (di default è vero). Inoltre, la struttura http.maxConnections java indica il numero massimo di (simultanee) connessioni per destinazione necessari per essere mantenute vive in un dato momento.

Pertanto un "uso forza di HTTP1.0" potrebbe essere applicato per l'intera applicazione contemporaneamente impostando la http.keepAlive proprietà Java false.

Hmmh. I può essere manca qualcosa qui (poiché questa è una vecchia questione), ma per quanto ne so, ci sono 2 modi ben noti a forza di chiusura della connessione TCP sottostante:

  • Forza l'utilizzo di HTTP 1.0 (1.1 connessioni persistenti introdotte) - questo come indicato dalla linea di richiesta HTTP
  • Inviare 'connessione' intestazione con valore 'vicino'; questo costringerà la chiusura pure.

L'abbandono flussi causerà le connessioni TCP inattive. Il flusso di risposta deve essere letto completamente. Un'altra cosa che ho trascurato inizialmente, e hanno visto trascurato nella maggior parte delle risposte su questo argomento è dimenticare di affrontare il flusso di errore in caso di eccezioni. Codice simile a questo uno fisso delle mie applicazioni che non è stato liberando risorse correttamente:

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();
    }
}

Il lettore di buffer non è strettamente necessario, l'ho scelto perché il mio caso d'uso necessario leggere una riga alla volta.

Vedi anche: http: // docs .oracle.com / JavaSE / 1.5.0 / docs / guide / net / http-keepalive.html

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top