2012-11-23 103 views
1

我的Android代碼始終發送數據,它似乎正在工作,直到拋出完全意外的IOException,從而凍結所有內容。我不明白爲什麼我可以發送幾個請求沒有問題,直到例外出現,幾乎是隨機的。這裏是我的代碼:當我嘗試通過HttpsUrlConnection發送帖子時發生意外的IOException異常

public class HttpsClient { 

private final static String TAG = "HttpsClient"; 

private final static String TOKEN_HEADER_KEY = "Token"; 

private final String urlString; 

private SSLContext sslContext; 

// application-specific HTTP header 
private String TokenHeaderValue = null; 



public HttpsClient(String host, String path) { 
    // this.sslContext will be init'ed in open() 
    this.urlString = "https://" + host + ":443/" + path; 
} 


public boolean open() { 
    try { 
     this.sslContext = SSLContext.getInstance("TLS"); 
     this.sslContext.init(null, null, new java.security.SecureRandom()); 
     return true; 
    } catch (NoSuchAlgorithmException e) { 
     Logger.e(TAG, "NoSuchAlgorithmException:"); 
    } catch (KeyManagementException e) { 
     Logger.e(TAG, "KeyManagementException:"); 
    } 

    return false; 
} 


public byte[] send(byte[] req) { 

    Logger.d(TAG, "sending " + Utils.byteArrayToString(req) + " to " + this.urlString); 

    URL url; 
    try { 
     url = new URL(this.urlString); 
    } catch (MalformedURLException e) { 
     Logger.e(TAG, "MalformedURLException:"); 
     return null; 
    } 
    HttpsURLConnection connection; 
    try { 
     connection = (HttpsURLConnection) url.openConnection(); 
    } catch (IOException e) { 
     Logger.e(TAG, "send IOException 1 " + ((null == e.getMessage()) ? e.getMessage() : "")); 
     e.printStackTrace(); 
     return null; 
    } 

    connection.setDoInput(true); 
    connection.setDoOutput(true); 
    connection.setRequestProperty("Connection", "close"); 
    try { 
     connection.setRequestMethod("POST"); 

    } catch (ProtocolException ignored) { } 
    connection.setSSLSocketFactory(this.sslContext.getSocketFactory()); 
    connection.setReadTimeout(3000); 



    if (this.TokenHeaderValue != null) 
     connection.setRequestProperty(TOKEN_HEADER_KEY, this.TokenHeaderValue); 



    { 
     final Map<String, List<String>> requestProps = connection.getRequestProperties(); 
     Logger.d(TAG, requestProps.size() + " Request header(s):"); 
     for (Map.Entry<String, List<String>> entry : requestProps.entrySet()) 
      for (String value : entry.getValue()) 
       Logger.d(TAG, " " + entry.getKey() + ": <" + value + ">"); 
    } 

    try { 
     // open up the output stream of the connection 
     DataOutputStream output = new DataOutputStream(connection.getOutputStream()); 

     // write out the data 
     output.write(req, 0, req.length); 
     output.flush(); 


     Logger.i(TAG, "Response Code: " + connection.getResponseCode()); 
     Logger.i(TAG, "Response Message: " + connection.getResponseMessage()); 
    } catch (SocketTimeoutException e) { 
     Logger.e(TAG, "SocketTimeoutException:" + ((null == e.getMessage()) ? e.getMessage() : "")); 
     return null; 
    } catch (IOException e) { // FAILS HERE !!!!!!! 
     Logger.e(TAG, "send IOException 2 " + ((null == e.getMessage()) ? e.getMessage() : "")); 
     return null; 
    } 


    final Map<String, List<String>> responseHeaderFields = connection.getHeaderFields(); 
    Logger.d(TAG, responseHeaderFields.size() + " Response header(s):"); 
    for (Map.Entry<String, List<String>> entry : responseHeaderFields.entrySet()) { 
     final String key = entry.getKey(); 
     if ((null != key) && key.equals(TOKEN_HEADER_KEY)) 
      this.TokenHeaderValue = entry.getValue().get(0); 
     for (String value : entry.getValue()) 
      Logger.d(TAG, " " + key + ": <" + value + ">"); 
    } 


    // read response 
    ArrayList<Byte> response = new ArrayList<Byte>(); 

    try { 
     DataInputStream input = new DataInputStream(connection.getInputStream()); 

     // read in each character until end-of-stream is detected 
     for(int c = input.read(); c != -1; c = input.read()) { 
      response.add((byte) c); 
     } 
     Logger.w(TAG, "Https connection is " + connection); 
     connection.disconnect(); 
     Logger.w(TAG, "Https connection is " + connection); 
     input.close(); 

    } catch (IOException e) { 
     Logger.e(TAG, "send IOException 3 " + ((null == e.getMessage()) ? e.getMessage() : "")); 
     return null; 
    } 

    if (0 == response.size()) { 
     Logger.w(TAG, "response is null"); 

     return null; 
    } 

    // else 

    byte[] result = new byte[response.size()]; 
    for (int i = 0; i < result.length; i++) 
     result[i] = response.get(i).byteValue(); 

    Logger.i(TAG, "Response payload: " + Utils.byteArrayToString(result)); 



    return result;   
} 
} 

我再說一遍:代碼工作「許多郵局發送後直到,然後崩潰」的IO異常的原因。而且,服務器很好,我的代碼有問題。

這裏就是整個錯誤堆棧跟蹤:

send IOException 2 

0: org.apache.harmony.xnet.provider.jsse.NativeCrypto.SSL_read_byte(Native Method) 

1: org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl$SSLInputStream.read(OpenSSLSocketImpl.java:783) 

2: org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.readLine(HttpURLConnectionImpl.java:671) 

3: org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.readResponseHeaders(HttpURLConnectionImpl.java:699) 

4: org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.getFromNetwork(HttpURLConnectionImpl.java:1088) 

5: org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.retrieveResponse(HttpURLConnectionImpl.java:1041) 

6: org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:736) 

7: org.apache.harmony.luni.internal.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:146) 

8: com.bitstorms.gui.channels.HttpsClient.send(HttpsClient.java:117) 

9: com.bitstorms.gui.apps.Application$MyRunnable.run(Application.java:81) 

10: java.lang.Thread.run(Thread.java:1020) 

回答

0

可疑的一點是,你從來沒有正確地釋放流。例如,您創建DataOutputStream output,使用它,但從不關閉。嘗試改變使用finally代碼以關閉流:

DataOutputStream output = null; 
try { 
    output = new DataOutputStream(connection.getOutputStream()); 
    ... 
} catch (...) { 
    ... 
} finally { 
    if (output != null) { 
     try { 
      output.close(); 
     } catch (IOException ignored) {} 
    } 
} 

同樣應該DataInputStream inputconnection本身來完成(但應在guaranteedly一些全球finally部分關閉)。

+0

我試圖把你正在談論的最後一節關閉流(輸入也),但沒有什麼,代碼的行爲是一樣的......我不明白... –

+0

@FrancescoNovecentoNicolosi:然後我走出想法。您可以發佈錯誤堆棧跟蹤(您可以編輯您的初始帖子並將其追加到堆棧跟蹤中)。可能它可以提供一些想法。 –

+0

剛編輯我的問題。提供整個堆棧跟蹤,你看到了嗎? –

相關問題