0

我正在使用 HttpURLConnection 向网站发送 POST 以登录用户。我的代码:

byte[] queryBytes = query.toString().getBytes();

/* Open the connection to the login page */
URL url = new URL( urlString );
HttpURLConnection connection = (HttpURLConnection)url.openConnection();

connection.setConnectTimeout( CONNECTION_TIMEOUT );
connection.setReadTimeout( CONNECTION_TIMEOUT );
connection.setRequestProperty( "Accept", "text/html, application/octet-stream" );
connection.setRequestProperty( "Cache-Control", "max-age=0" );

connection.setFixedLengthStreamingMode( queryBytes.length );
connection.setRequestProperty( "Content-Type", "application/x-www-form-urlencoded" );
connection.setRequestProperty( "Origin", ORIGIN );
connection.setRequestProperty( "Referer", REFERER );

/* Add POST data string */
connection.setDoOutput( true );
outputStream = connection.getOutputStream();
outputStream.write( queryBytes );
outputStream.close();

/* Execute the POST connection */
int code = connection.getResponseCode();

这会在最后一行使用以下 logcat 导致 IOException:

06-15 12:03:53.285: E/MyApp(1856): Login: IOException: Read timed out
06-15 12:03:53.285: E/MyApp(1856): java.net.SocketTimeoutException: Read timed out
06-15 12:03:53.285: E/MyApp(1856):  at org.apache.harmony.xnet.provider.jsse.NativeCrypto.SSL_read(Native Method)
06-15 12:03:53.285: E/MyApp(1856):  at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl$SSLInputStream.read(OpenSSLSocketImpl.java:675)
06-15 12:03:53.285: E/MyApp(1856):  at libcore.io.Streams.readSingleByte(Streams.java:41)
06-15 12:03:53.285: E/MyApp(1856):  at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl$SSLInputStream.read(OpenSSLSocketImpl.java:659)
06-15 12:03:53.285: E/MyApp(1856):  at libcore.io.Streams.readAsciiLine(Streams.java:201)
06-15 12:03:53.285: E/MyApp(1856):  at libcore.net.http.HttpEngine.readResponseHeaders(HttpEngine.java:560)
06-15 12:03:53.285: E/MyApp(1856):  at libcore.net.http.HttpEngine.readResponse(HttpEngine.java:813)
06-15 12:03:53.285: E/MyApp(1856):  at libcore.net.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:274)
06-15 12:03:53.285: E/MyApp(1856):  at libcore.net.http.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:486)
06-15 12:03:53.285: E/MyApp(1856):  at libcore.net.http.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:134)
06-15 12:03:53.285: E/MyApp(1856):  at com.myapp.interfaces.SkyWestInterface.login(SkyWestInterface.java:606)
06-15 12:03:53.285: E/MyApp(1856):  at com.myapp.services.MonthUpdateService.processIntent(MonthUpdateService.java:181)
06-15 12:03:53.285: E/MyApp(1856):  at com.myapp.services.UpdateService.onHandleIntent(UpdateService.java:237)
06-15 12:03:53.285: E/MyApp(1856):  at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:65)
06-15 12:03:53.285: E/MyApp(1856):  at android.os.Handler.dispatchMessage(Handler.java:99)
06-15 12:03:53.285: E/MyApp(1856):  at android.os.Looper.loop(Looper.java:137)
06-15 12:03:53.285: E/MyApp(1856):  at android.os.HandlerThread.run(HandlerThread.java:60)

如果我删除该connection.setFixedLengthStreamingMode( queryBytes.length );行,那么它可以工作。为什么这条线会导致超时?是因为 SSL 吗?

4

1 回答 1

0

您是否尝试OutputStream在调用后刷新write()close()应该自动调用,flush()但调用 toflush()可能会有所帮助。

可能发生的情况是调用setFixedLengthStreamingMode()导致 HTTP 请求使用Content-Length: <number>标头而不是Transfer-Encoding: chunked标头。在这种模式下,线路另一端的 HTTP 服务器甚至不会开始处理请求,直到它<number>从线路中读取字节。如果在对底层的阻塞调用之前你不刷新OutputStream并且所有字节都没有被写入,那么服务器将永远不会响应,并且你每次都会超时。read()connection.getResponseCode()

我的假设是,当Content-Length设置时,并非所有字节都被写入,并且另一端的服务器永远不会开始处理请求,但是当Transfer-Encoding设置时,那么(a)所有字节最终都会因任何原因而被写入,或者 (b) 另一端的服务器在请求进入时立即开始处理请求,并且服务器在构建响应的过程中提取所有字节。

无论如何,我建议flush()您在write(). 如果可行,您可以使用Wireshark确认这一理论。如果这不起作用,我建议无论如何都要断开Wireshark来诊断问题。:)

于 2013-06-15T19:35:05.213 回答