2010-02-17 33 views
8

[Java 1.5; Eclipse Galileo]HttpsURLConnection se estanca cuando getInputStream() se llama

HttpsURLConnection parece bloquearse cuando se llama al método getInputStream(). He intentado utilizar diferentes sitios web en vano (actualmente https://www.google.com). Debo señalar que estoy usando http S.

El siguiente código se ha modificado en función de lo que he aprendido de otras respuestas de StackOverflow. Sin embargo, ninguna solución que he probado hasta ahora ha funcionado.

estaría muy agradecido por un empujón en la dirección correcta :)

public static void request(URL url, String query) 
{ 
try{ 

    HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); 

    //connection.setReadTimeout(5000); //<-- uncommenting this line at least allows a timeout error to be thrown 

    connection.setDoInput(true); 
    connection.setDoOutput(true); 
    connection.setUseCaches(false); 
    System.setProperty("http.keepAlive", "false"); 


    connection.setRequestMethod("POST"); 


    // setting headers 
    connection.setRequestProperty("Content-length",String.valueOf (query.length())); 
    connection.setRequestProperty("Content-Type","application/x-www-form-urlencoded"); //WAS application/x-www- form-urlencoded 
    connection.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt)"); 

    //////////////////////////////////////////////////////////////////////////////////// 
    //////////////////////////////////////////////////////////////////////////////////// 
    System.out.println("THIS line stalls" + connection.getInputStream()); 
    //////////////////////////////////////////////////////////////////////////////////// 

}catch(Exception e) { 
    System.out.println(e); 
    e.printStackTrace(); 
} 

errores típicos se parecen:

java.net.SocketTimeoutException: Read timed out 
at java.net.SocketInputStream.socketRead0(Native Method) 
at java.net.SocketInputStream.read(SocketInputStream.java:129) 
at com.sun.net.ssl.internal.ssl.InputRecord.readFully(InputRecord.java:293) 
at com.sun.net.ssl.internal.ssl.InputRecord.read(InputRecord.java:331) 
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:782) 
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:739) 
at com.sun.net.ssl.internal.ssl.AppInputStream.read(AppInputStream.java:75) 
at java.io.BufferedInputStream.fill(BufferedInputStream.java:218) 
at java.io.BufferedInputStream.read1(BufferedInputStream.java:256) 
at java.io.BufferedInputStream.read(BufferedInputStream.java:313) 
at sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:681) 
at sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:626) 
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:983) 
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:234) 
at https_understanding.HTTPSRequest.request(HTTPSRequest.java:60) 
at https_understanding.Main.main(Main.java:17) 
+0

Sólo una puñalada en la oscuridad, usted está enviando una solicitud POST, lo que podría suponer que el otro extremo (Google) está esperando para que usted envíe algunos parámetros. Todo lo que está enviando es algunos encabezados HTTP. ¿Qué sucede cuando cambias POST a GET? – beny23

+0

¿Qué estás/realmente/tratando de hacer? Su etiqueta de Gmail me lleva a sospechar que podría estar mejor con POP, IMAP o SMTP (o una de las API personalizadas de Google) –

Respuesta

5
connection.setDoOutput(true); 

Esto significa que usted tiene que abrir, escribir y cierre la secuencia de salida de la conexión antes de intentar leer de su flujo de entrada. Ver the docs.

+0

Esto también establece implícitamente el método de solicitud en 'POST' cuando el protocolo HTTP se usa en URL, en otras palabras , el 'connection.setRequestMethod (" POST ");' es completamente superfloo (como lo es downcast a 'HttpUrlConnection'). Haga un 'connection.getOutputStream(). Close()' si tiene la intención de activar un POST sin ningún parámetro de solicitud (lo cual no tiene ningún sentido, pero está bien;)). – BalusC

+3

esto no hizo nada para resolver el problema –

2

Además, no establezca el encabezado de longitud del contenido. Java hará eso por ti.

+0

Gracias por el consejo :) – geraldalewis

3

que reproduce el problema en Android 2.2: cuando se descarga desde un servidor web de forma inalámbrica y una dirección URL HTTPS, el error es un socket "leer el tiempo de espera" en URLConnection.getInputStream()

Para solucionarlo, utilice url.openStream() para el InputStream en lugar de connection.getInputStream()

Bono: se puede obtener la longitud del archivo que está descargando para que pueda mostrar un indicador completo%

ejemplo de código:

private final int TIMEOUT_CONNECTION = 5000;//5sec 
private final int TIMEOUT_SOCKET = 30000;//30sec 

file = new File(strFullPath); 
URL url = new URL(strURL); 
URLConnection ucon = url.openConnection(); 

//this timeout affects how long it takes for the app to realize there's a connection problem 
ucon.setReadTimeout(TIMEOUT_CONNECTION); 
ucon.setConnectTimeout(TIMEOUT_SOCKET); 


//IMPORTANT UPDATE: 
// ucon.getInputStream() often times-out over wireless 
// so, replace it with ucon.connect() and url.openStream() 
ucon.connect(); 
iFileLength = ucon.getContentLength();//returns -1 if not set in response header 

if (iFileLength != -1) 
{ 
    Log.i(TAG, "Expected Filelength = "+String.valueOf(iFileLength)+" bytes"); 
} 

//Define InputStreams to read from the URLConnection. 
// uses 5KB download buffer 
InputStream is = url.openStream();//ucon.getInputStream(); 
BufferedInputStream inStream = new BufferedInputStream(is, 1024 * 5); 
outStream = new FileOutputStream(file); 
bFileOpen = true; 
byte[] buff = new byte[5 * 1024]; 

//Read bytes (and store them) until there is nothing more to read(-1) 
int total=0; 
int len; 
int percentdone; 
int percentdonelast=0; 
while ((len = inStream.read(buff)) != -1) 
{ 
    //write to file 
    outStream.write(buff,0,len); 

    //calculate percent done 
    if (iFileLength != -1) 
    { 
     total+=len; 
     percentdone=(int)(total*100/iFileLength); 

     //limit the number of messages to no more than one message every 10% 
     if ((percentdone - percentdonelast) > 10) 
     { 
      percentdonelast = percentdone; 
      Log.i(TAG,String.valueOf(percentdone)+"%"); 
     } 
    } 
} 

//clean up 
outStream.flush();//THIS IS VERY IMPORTANT ! 
outStream.close(); 
bFileOpen = false; 
inStream.close();