web-dev-qa-db-fra.com

HttpUrlConnection.openConnection échoue une deuxième fois

Je sais que ce problème devrait être résolu avec System.setProperty ("http.keepAlive", "false"); avant openConnection, mais cela n'a pas fonctionné pour moi. Essayez d'abord ce code, le second échoue. Même si j'essaie cette demande après moins de 5 secondes, cela fonctionne également. Si j'attends plus que ça, ça échoue encore

Voici mon code:

    System.setProperty("http.keepAlive", "false");
  HttpURLConnection conn = (HttpURLConnection) mURL.openConnection();
  conn.setUseCaches(false); 
  conn.setRequestProperty("Connection","Keep-Alive"); 
  conn.setRequestProperty("User-Agent", useragent);
  conn.setConnectTimeout (30000) ; 
  conn.setDoOutput(true); 
        conn.setDoInput(true); 

  consumer.sign(conn);
  InputSource is = new InputSource(conn.getInputStream());

Je reçois l'exception à la dernière ligne:

Java.io.IOException: Write error: I/O error during system call, Broken pipe
W/System.err( 2164):  at org.Apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.nativewrite(Native Method)
W/System.err( 2164):  at org.Apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.access$600(OpenSSLSocketImpl.Java:55)
W/System.err( 2164):  at org.Apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl$SSLOutputStream.write(OpenSSLSocketImpl.Java:583)
W/System.err( 2164):  at Java.io.OutputStream.write(OutputStream.Java:82)
W/System.err( 2164):  at org.Apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.sendRequest(HttpURLConnectionImpl.Java:1332)
W/System.err( 2164):  at org.Apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.doRequestInternal(HttpURLConnectionImpl.Java:1656)
W/System.err( 2164):  at org.Apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.doRequest(HttpURLConnectionImpl.Java:1649)
W/System.err( 2164):  at org.Apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.Java:1153)
W/System.err( 2164):  at org.Apache.harmony.luni.internal.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.Java:253)

Quelqu'un at-il une idée de ce qui ne va pas ici?. Merci!

32
ggomeze

J'ai résolu le problème. Ici, je vous laisse le code, au cas où cela pourrait être utile pour quelqu'un. Fondamentalement, je vois une tendance sur Google pour utiliser HttpClient/HttpGet au lieu de HttpUrlConnection. J'ai donc essayé avec ces cours, et tout a fonctionné:

final HttpClient client = new DefaultHttpClient();
final HttpGet conn = new HttpGet(mURL.toString());

OAuthConsumer consumer = mOAuthManager.getPostConsumer();
consumer.sign(conn);
HttpResponse response = client.execute(conn);
InputSource is = new InputSource(response.getEntity().getContent());
3
ggomeze

Le pool de connexions utilisé par HttpURLConnection lorsqu'il maintient des connexions actives est rompu de sorte qu'il essaie d'utiliser des connexions qui ont été fermées par le serveur. Par défaut Android définit KeepAlive sur toutes les connexions.

System.setProperty("http.keepAlive", "false"); est une solution de contournement qui désactive KeepAlive pour toutes les connexions afin d'éviter le bogue dans le pool de connexions.

conn.setRequestProperty("Connection","Keep-Alive"); active KeepAlive pour cette connexion particulière, inversant essentiellement ce que fait System.setProperty("http.keepAlive", "false");.

Aussi j'appelle toujours explicitement connect() car cela indique clairement où vous mettez fin à votre configuration de connexion. Je ne sais pas si l'appel de cette méthode est facultatif ou non.

System.setProperty("http.keepAlive", "false");
HttpURLConnection conn = (HttpURLConnection) mURL.openConnection();
conn.setUseCaches(false); 
conn.setRequestProperty("User-Agent", useragent);
conn.setConnectTimeout(30000);
conn.setDoOutput(true); 
conn.setDoInput(true); 
consumer.sign(conn);

conn.connect();

InputSource is = new InputSource(conn.getInputStream());
29
barrycburton

Vous n'avez pas besoin de la System.setProperty("http.keepAlive", "false");

Tout ce dont vous avez besoin est conn.setRequestProperty("connection", "close");

cela résout le problème, mais tue efficacement les personnes en vie et peut donc potentiellement ralentir plusieurs connexions (ce qui est dommage). Je regardais à travers le tracker de bug d'harmonie mais je n'ai rien trouvé.

@fonetik, savez-vous si cela est déjà soulevé avec harmonie? Je ne veux pas dire que cela aide beaucoup car un autre défaut luni lié à http n'est toujours pas attribué après plus d'un mois.

24
RaB

ce bogue a été corrigé dans la version Android 2.3, car nous savons que System.setProperty("http.keepAlive", "false"); n'est pas une très bonne solution, car sur un appareil mobile, créer chaque connexion est chaque fois que cela coûte cher.

1
allen

Je crois que votre problème réside dans l'ordre de votre code. Vérifiez ces méthodes dans URLConnection JavaDocs - setRequestProperty ne doit pas être appelé une fois la connexion établie sur mUrl.openConnection (). Cela peut fonctionner la première fois car la connexion est établie, puis vous modifiez les paramètres qui n'affectent rien jusqu'à la prochaine fois que vous essayez d'établir une connexion. Essayez plutôt d'utiliser le constructeur HttpURLConnection pour pouvoir appeler connect () après avoir défini les propriétés.

0
ZachM

Lorsque j'essaie d'ouvrir la connexion https, cela fonctionne bien, mais la deuxième fois, il échoue car j'ai défini la valeur de la propriété système au lieu de la connexion HttpsURLConnection. J'ai le Java.io.IOException: Erreur d'écriture: problème d'E/S lors de la deuxième ouverture de la connexion https. J'ai utilisé le code suivant dans mon application.

System.setProperty("http.proxyHost", proxy);
System.setProperty("http.proxyPort", port);

Mais quand j'ai changé la même chose en dessous, cela fonctionne bien.

javax.net.ssl.HttpsURLConnection ucon = (javax.net.ssl.HttpsURLConnection) urlWPF.openConnection(proxyserver);

ucon.setRequestProperty("http.proxyHost", proxy);
ucon.setRequestProperty("http.proxyPort", port);

Si vous définissez la propriété système, elle s'appliquera à toute l'application. Si vous souhaitez réinitialiser le même, vous pouvez suivre deux façons. Le premier est que vous devez prendre l'actualisation du serveur et le second est que vous devez changer le HttpsURLConnection.setRequestProperty qui est mentionné ci-dessus si nécessaire.

0
user3411924