문제

내가 사용하는 라이브러리 (Signpost 1.1-snapshot)가 원격 서버에 두 번 연속 연결되는 경우 Android 1.5에서 독특한 문제가 발생하는 것 같습니다. 두 번째 연결은 항상 a로 실패합니다 HttpURLConnection.getResponseCode()-1

다음은 문제를 노출시키는 테스트 케이스입니다.

// BROKEN
public void testDefaultOAuthConsumerAndroidBug() throws Exception {
    for (int i = 0; i < 2; ++i) {
        final HttpURLConnection c = (HttpURLConnection) new URL("https://api.tripit.com/oauth/request_token").openConnection();
        final DefaultOAuthConsumer consumer = new DefaultOAuthConsumer(api_key, api_secret, SignatureMethod.HMAC_SHA1);
        consumer.sign(c);                             // This line...
        final InputStream is = c.getInputStream();
        while( is.read() >= 0 ) ;                     // ... in combination with this line causes responseCode -1 for i==1 when using api.tripit.com but not mail.google.com
        assertTrue(c.getResponseCode() > 0);
    }
}

기본적으로 요청에 서명 한 다음 전체 입력 스트림을 소비하면 다음 요청이 -1의 결과 코드로 실패합니다. 입력 스트림에서 하나의 문자를 읽는 경우 실패는 발생하지 않는 것 같습니다.

위의 URL과 같은 특정 URL 만 발생하지 않습니다.

또한 httpurlconnection 대신 httpclient로 전환하면 모든 것이 잘 작동합니다.

// WORKS
public void testCommonsHttpOAuthConsumerAndroidBug() throws Exception {
    for (int i = 0; i < 2; ++i) {
        final HttpGet c = new HttpGet("https://api.tripit.com/oauth/request_token");
        final CommonsHttpOAuthConsumer consumer = new CommonsHttpOAuthConsumer(api_key, api_secret, SignatureMethod.HMAC_SHA1);
        consumer.sign(c);
        final HttpResponse response = new DefaultHttpClient().execute(c);
        final InputStream is = response.getEntity().getContent();
        while( is.read() >= 0 ) ;
        assertTrue( response.getStatusLine().getStatusCode() == 200);
    }
}

내가 찾았 어 참조 다른 곳에서는 비슷한 문제인 것처럼 보이지만 지금까지는 해결책이 없습니다. 그들이 진정으로 같은 문제라면, 다른 참조가 그것을 언급하지 않기 때문에 문제는 아마도 징후가 아닐 것입니다.

어떤 아이디어?

도움이 되었습니까?

해결책

이 속성을 설정하여 도움이되는지 확인하십시오.

http.keepAlive=false

URLConnection에 의해 서버 응답을 이해하지 못하고 클라이언트/서버가 동기화되지 않으면 비슷한 문제를 보았습니다.

이것이 당신의 문제를 해결하면, 당신은 응답에 대한 특별한 것을 정확하게보기 위해 HTTP 추적을 가져와야합니다.

편집 :이 변화는 단지 내 의심을 확인합니다. 문제를 해결하지 못합니다. 그것은 단지 증상을 숨 깁니다.

첫 번째 요청의 응답이 200 인 경우 추적이 필요합니다. 나는 일반적으로 Ethereal/Wireshark를 사용하여 TCP 추적을 얻습니다.

첫 번째 응답이 200이 아닌 경우 코드에 문제가 있습니다. OAUTH를 사용하면 오류 응답 (401)은 실제로 DepoyAdVice, Signature Base String 등을 포함하여 Debug에 도움이되는 데이터를 반환합니다. 오류 스트림에서 모든 것을 읽어야합니다. 그렇지 않으면 다음 연결을 혼동 할 것이며 이것이 -1의 원인입니다. 다음 예제는 오류를 올바르게 처리하는 방법을 보여줍니다.

public static String get(String url) throws IOException {

    ByteArrayOutputStream os = new ByteArrayOutputStream();
    URLConnection conn=null;
    byte[] buf = new byte[4096];

    try {
        URL a = new URL(url);
        conn = a.openConnection();
        InputStream is = conn.getInputStream();
        int ret = 0;
        while ((ret = is.read(buf)) > 0) {
            os.write(buf, 0, ret);
        }
        // close the inputstream
        is.close();
        return new String(os.toByteArray());
    } catch (IOException e) {
        try {
            int respCode = ((HttpURLConnection)conn).getResponseCode();
            InputStream es = ((HttpURLConnection)conn).getErrorStream();
            int ret = 0;
            // read the response body
            while ((ret = es.read(buf)) > 0) {
                os.write(buf, 0, ret);
            }
            // close the errorstream
            es.close();
            return "Error response " + respCode + ": " + 
               new String(os.toByteArray());
        } catch(IOException ex) {
            throw ex;
        }
    }
}

다른 팁

입력 스트림의 모든 데이터를 닫고 두 번째 연결을 열기 전에 읽지 않았을 때 동일한 문제가 발생했습니다. 또한 고정되었습니다 System.setProperty("http.keepAlive", "false"); 또는 나머지 입력 스트림을 읽을 때까지 단순히 반복됩니다.

문제와 완전히 관련이 없지만 이것이 비슷한 문제를 가진 다른 사람에게 도움이되기를 바랍니다.

Google은 Froyo 이전에 발생하기 때문에 우아한 해결 방법을 제공했습니다.

private void disableConnectionReuseIfNecessary() {
    // HTTP connection reuse which was buggy pre-froyo
    if (Integer.parseInt(Build.VERSION.SDK) < Build.VERSION_CODES.FROYO) {
        System.setProperty("http.keepAlive", "false");
    }
}

cf. http://android-developers.blogspot.ca/2011/09/androids-http-clients.html

또는 연결 상태에서 HTTP 헤더를 설정할 수 있습니다 (httpurlConnection) :

conn.setRequestProperty("Connection", "close");

응답 읽기를 마치기 전에 연결이 닫히지 않았 음을 확인할 수 있습니까? httpclient가 응답 코드를 즉시 구문 분석하고 향후 쿼리를 위해 저장하지만 연결이 닫히면 httpurlconnection이 -1을 반환 할 수 있습니까?

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top