2012-11-23 2 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;   
} 
} 

: 여기 내 코드의 코드가 작동 '많은 게시물을 보낸 후 TIL, 다음 충돌'는 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

방금 ​​내 질문을 편집했습니다. 전체 스택 추적을 제공 했습니까? –