SSLProtocolException阅读在Android 2.3.3设备的https响应时 [英] SSLProtocolException when reading https responses on Android 2.3.3 devices
问题描述
我面临着一个错误的问题(<一href="http://$c$c.google.com/p/android/issues/detail?id=16121&can=1&q=sslexception&colspec=ID%20Type%20Status%20Owner%20Summary%20Stars"相对=nofollow>发行16121 )被引入姜饼2.3.3和固定2.3.4。
I'm facing a problem with a bug (Issue 16121) that was introduced in Gingerbread 2.3.3 and fixed with 2.3.4.
读取HTTPS请求的响应读取〜40KB从InputStream后抛出 SSLProtocolException
。这个问题在<一个描述href="http://$c$c.google.com/p/android/issues/detail?id=16121&can=1&q=sslexception&colspec=ID%20Type%20Status%20Owner%20Summary%20Stars"相对=nofollow>发行16121 。在页面的底部是一个<一个href="http://android.google$c$c.com/issues/attachment?aid=-2469130209445272620&name=BugReport.zip&token=319ba797244f948d7e530fe56ccce452"相对=nofollow> Android项目,揭示了问题。错误报告来源于用户亚历克斯的计算器(问题)。
Reading the response of a https request throws an SSLProtocolException
after reading ~40kB from the inputstream. The problem is described at Issue 16121. At the bottom of the page is a android project that reveals the bug. The bug report originates from user 'Alex' on stackoverflow (question).
我在发送许多不同的HTTPS请求市场的应用程序。他们中的大多数需要获得高达200kB的。我不能改变在服务器端任何东西。我用的是 DefaultHttpClient
发送HTTPS请求。
I have an app in the market that sends many different https requests. Most of them need to receive up to 200kB. I cannot change anything on the server side. I use the DefaultHttpClient
to send https requests.
- 如何有效地解决这个问题?
- 使用不同的HTTPS的API?其中HTTPS API?
推荐答案
下面是一些抽样的方法,如评论所指出的,我使用的<一个href="http://www.java2s.com/Tutorial/Java/0180__File/AnInputStreamclassthatterminatesthestreamwhenitencountersaparticularbytesequence.htm"相对=nofollow> CharTerminatedInputStream
,在Apache许可证下。该网址,看看它是在注释中也是如此。
Here are some sample methods, as noted in the comment, I am using CharTerminatedInputStream
, under the Apache license. The URL to see it is in the comment as well.
private static final int BUFFER_SIZE = 4096;
private static final char[] TERMINATOR = new char[]{'\r', '\n', '\r', '\n'};
/**
* Simple SSL connect example to avoid Issue 15356 on Android 2.3.3
*
* @param host The host/server name
* @param port The TCP port to use (443 is default for HTTP over SSL)
* @param file The file you are requesting (/path/to/file/on/server.doc)
* @param fileOut Your <code>OutputStream</code> for the file you are writing to
* @throws Exception If any error occurs - obviously should be improved for your implementation
*/
private static void downloadFileOverSSL(String host, int port, String file, OutputStream fileOut) throws Exception {
PrintWriter socketOut = null;
InputStream socketIn = null;
try {
// create a socket to talk to the server on
SocketFactory factory = SSLSocketFactory.getDefault();
Socket socket = factory.createSocket(host, port);
// we'll use this to send our request to the server
socketOut = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
//This is what Java was sending using URLConnection, and it works here too...
// You can always change this to something both your app and server will understand depending how it is setup
// This is the least you need in the request:
/*String requestStr = "GET " + file + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"\r\n";*/
String requestStr = "GET " + file + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"User-Agent: Java/1.6.0_25\r\n" +
"Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2" +
"Connection: keep-alive\r\n" +
"\r\n";
//Log.i(getLogTag(), "Request being sent: `" + requestStr + "\"");
// send the request to the server
socketOut.print(requestStr);
socketOut.flush();
// this reads the server's response
socketIn = socket.getInputStream();
/*
Write the results into our local file's output stream
*/
// This is the tricky part, the raw socket returns the HTTP 200 response and headers.
// This can probably be optimized, but it's just reading through until it finds \r\n\r\n
// You can use something like CharTerminatedInputStream
// (ref: http://www.java2s.com/Tutorial/Java/0180__File/AnInputStreamclassthatterminatesthestreamwhenitencountersaparticularbytesequence.htm)
CharTerminatedInputStream charTermInput = new CharTerminatedInputStream(socketIn, TERMINATOR);
while (charTermInput.read() != -1) {
// -1 indicates a match was made, IOException or ProtocolException thrown if match not made by end of stream
}
int numBytesRead;
byte[] buffer = new byte[BUFFER_SIZE];
while ((numBytesRead = socketIn.read(buffer, 0, BUFFER_SIZE)) != -1) {
fileOut.write(buffer, 0, numBytesRead);
//Log.d(getLogTag(), "Reading data [" + numBytesRead + "]: " + new String(buffer, 0, numBytesRead));
}
fileOut.flush();
} finally {
safeClose(socketOut);
safeClose(socketIn);
safeClose(fileOut);
}
}
private static void safeClose(Closeable closeable) {
if (closeable != null) {
try {
closeable.close();
} catch (IOException ioe) {
//Log.w(getLogTag(), "Failed to close stream", ioe);
}
}
}
这篇关于SSLProtocolException阅读在Android 2.3.3设备的https响应时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!