안녕하세요,
DefaultHttpClient 를 이용해서, 서버와 통신하는 앱을 만들었습니다.
그런데, 이게 재미있는 현상이 있습니다.
가끔 통신이 되지 않는 건데요,
공유기 상태에서 여러가지 device를 물려 놓으면 안드로이드만 문제가 있습니다.
같은 서버로 아이폰, 안드로이드, pc 브라우저 3개를 이용해서 접속해 보면
pc브라우저와 아이폰은 동시에 아주 잘 접속되는데,
안드로이드는 다른 것들과 동시에 접속을 시도하면 안됩니다.
미치고 팔짝 뛰겠습니다. 한번 안되면 20초~1분 정도는 접속이 안됩니다.
어느 정도 시간이 지나면 정상적으로 접속되나, 또 동시에 시도하면 박살 납니다.
일단, 코드와 로그를 보면 재미있습니다. (사실 코드는 재미없고, 로그는 재미있습니다.)
(thread에서 접속부 구현이고요, 필요한 부분만.)
private HttpClient getHttpClient() {
HttpClient httpClient = null;
try {
final HttpParams params = new BasicHttpParams();
// PARAMS
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);
HttpConnectionParams.setConnectionTimeout(params, 1000 * 20); // 30s timeout.
HttpConnectionParams.setSoTimeout(params, 1000 * 20); // 30s timeout.
HttpConnectionParams.setSocketBufferSize(params, 512 * 1024);
HttpConnectionParams.setStaleCheckingEnabled(params, false);
HttpClientParams.setRedirecting(params, false);
params.setParameter(HttpProtocolParams.USE_EXPECT_CONTINUE, false);
// SCHEME
final SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
registry.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443));
final ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);
httpClient = new DefaultHttpClient(ccm, params);
} catch (Exception e) {
e.printStackTrace();
httpClient = new DefaultHttpClient();
}
return httpClient;
}
위 부분이 httpclient를 만드는 부분이고요, (참고로 서버는 keepalive off입니다)
String url = common.URL_CHECK;
ArrayList<NameValuePair> params = new ArrayList<NameValuePair>();
HttpPost httpPost = new HttpPost(url);
UrlEncodedFormEntity entityRequest = new UrlEncodedFormEntity(params, "UTF-8");
httpPost.setEntity(entityRequest);
HttpClient http =getHttpClient();
HttpResponse httpResponse = http.execute(httpPost);
HttpEntity entity = httpResponse.getEntity();
InputStream inStream = entity.getContent();
...............
요 부분이 실제 thread에서 통신하는 부분입니다.
이제 재미있는 로그를 볼 차례인데요,
로그는 제가 http packet generation까지 로그를 찍었으니까 재미있습니다(?)
첫번째는 잘 될 때의 로그 입니다.
11-11 15:49:59.449: D/libc(24344): DNS query requested to DNS proxy daemon hostname = xxxx.com
11-11 15:49:59.449: D/libc(24344): getaddrinfo proxy result code is = 222
11-11 15:49:59.449: D/libc(24344): getaddrinfo DNS proxy process success
11-11 15:49:59.479: D/org.apache.http.wire(24344): >> "POST /check.php HTTP/1.1[EOL]"
11-11 15:49:59.479: D/org.apache.http.wire(24344): >> "Content-Length: 0[EOL]"
11-11 15:49:59.479: D/org.apache.http.wire(24344): >> "Content-Type: application/x-www-form-urlencoded[EOL]"
11-11 15:49:59.479: D/org.apache.http.wire(24344): >> "Host: xxxxx.com[EOL]"
11-11 15:49:59.479: D/org.apache.http.wire(24344): >> "Connection: Keep-Alive[EOL]"
.............. (로그가 길어서 질문이 안올라가니까 생략)
11-11 15:49:59.600: D/org.apache.http.wire(24344): << "[{"success":true,"message":"wow","count":123}][\n]"
딱 보시면 아시겠지만,
될 때는 http.execute(httpPost) 를 하자마자 제대로 http packet을 만들어서 결과 200까지 받아오는 정상적인 코스를 밟죠. 열심히 handshake까지 열심히 합니다~!
그런데! 안될 때는
11-11 15:51:23.219: D/device(24344): 1080, 1920
11-11 18:16:47.318: D/matching_count(15086): org.apache.http.impl.client.DefaultHttpClient@43007968
11-11 15:51:23.219: D/matching_count(24344): after getHttpClient
11-11 15:51:23.229: D/libc(24344): DNS query requested to DNS proxy daemon hostname = xxxxx.com
11-11 15:51:23.229: D/libc(24344): getaddrinfo proxy result code is = 222
11-11 15:51:23.229: D/libc(24344): getaddrinfo DNS proxy process success
<----------- 바로 여기에서 패킷이 만들어져야 되는데 .... --------->
11-11 15:51:43.240: W/System.err(24344): org.apache.http.conn.ConnectTimeoutException: Connect to /11.11.11.1 timed out
11-11 15:51:43.240: W/System.err(24344): at org.apache.http.conn.scheme.PlainSocketFactory.connectSocket(PlainSocketFactory.java:121)
11-11 15:51:43.240: W/System.err(24344): at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:144)
11-11 15:51:43.250: W/System.err(24344): at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164)
11-11 15:51:43.250: W/System.err(24344): at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119)
....................... 중간 생략 .....................
11-11 15:51:43.260: W/System.err(24344): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465)
딱 이상하게 보이죠. execute를 했는데, paket을 만들지 않고, 멍 때리다가 일정 시간이 지나니까 timeout이 걸려 버립니다.
실제로 서버의 access_log를 살펴보면 access를 시도한 적이 없습니다.
그래서 중간에 debug로 혹시 defaultHttpClient가 null인가 싶어서 debugging log 찍어 보니 그것도 아닙니다. 뭔가 주소를 가져오긴 하는데, execute할 때 packet을 만들지 않고, 쐈다고 생각하는 것 같습니다.
이것을 어쩌면 좋을까요?
인류 최대의 숙제일까요, 아니면 죽을 때 까지 그냥 가져가야 할 버그일까요.
제가 무엇을 잘못하고 있는 걸까요?
해결 될 수 있는 조언을 해 주신 분께는
소개팅을... 할 수 있도록 노력해 보겠습니다. 와하하! (살려주세요)
아이구 머리야.