调用 getInputStream() 时 HttpsURLConnection 停止运行

发布于 2024-08-21 19:20:15 字数 2815 浏览 5 评论 0原文

[Java 1.5; Eclipse Galileo]

调用 getInputStream() 方法时,HttpsURLConnection 似乎停止运行。我尝试过使用不同的网站,但均无济于事(目前为 https://www.google.com)。我应该指出我正在使用 httpS

下面的代码是根据我从其他 StackOverflow 答案中了解到的内容进行修改的。然而,到目前为止我尝试过的解决方案都没有奏效。

我将非常感谢您在正确的方向上的推动:)

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

典型的错误如下所示:

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)

[Java 1.5; Eclipse Galileo]

HttpsURLConnection seems to stall when the getInputStream() method is called. I've tried using different websites to no avail (currently https://www.google.com). I should point out I'm using httpS.

The code below has been modified based on what I've learned from other StackOverflow answers. However, no solutions I've tried thus far have worked.

I'd be very grateful for a nudge in the right direction :)

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

Typical errors look like:

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)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

只有影子陪我不离不弃 2024-08-28 19:20:15
connection.setDoOutput(true);

这意味着您必须先打开、写入和关闭连接的输出流,然后才能尝试从连接的输入流中读取数据。请参阅文档

connection.setDoOutput(true);

This means that you have to open, write to, and close the connection's output stream before you attempt to read from its input stream. See the docs.

吻风 2024-08-28 19:20:15

我在 Android 2.2 中重现了这个问题:当通过无线和 HTTPS URL 从 Web 服务器下载时,错误是 URLConnection.getInputStream() 处的套接字“读取超时”

要修复它,请使用输入流的 url.openStream() 而不是 connection.getInputStream()

额外:您可以获取正在下载的文件的长度,以便显示完成百分比指示器

代码示例:

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

I reproduced the problem in Android 2.2: when downloading from a web-server over wireless and a HTTPS URL, the error is a socket "read time out" at URLConnection.getInputStream()

To fix it, use url.openStream() for the InputStream instead of connection.getInputStream()

Bonus: you can get the length of the file you're downloading so you can show a % complete indicator

code sample:

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();
山色无中 2024-08-28 19:20:15

也不要设置内容长度标头。 Java 会为你做这件事。

Also don't set the content-length header. Java will do that for you.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文