현재 사용중인 어플리케이션은 사진파일을 전화기로 전송하면 전화기에서 받은 사진파일을 보여주는 어플리케이션입니다. 지금까지 문제 없이 잘 사용하고 있었는데 웹 서버에 응답이 없는 전화기에 파일을 전송하려고 하다 보니 타임아웃 설정을 해도 커넥션이 종료되지 않는 문제가 생겼습니다. 커넥션이 종료가 되지 않으니 프로세스에는 계속 남아 있는 추가적인 문제까지…. 그래서 ‘조금 더 좋겠지’ 라는 막연한 기대감으로 HttpClient4.0 으로 버전업을 시도 했습니다.
// HttpClient 3.0 Source
String pushURL = "http://127.0.0.1/PushFile";
File f = new File("C:\\TEST\\beauty.jpg");
PostMethod filePost = new PostMethod(pushURL);
filePost.setFollowRedirects(false);
Part[] parts = { new FilePart("beauty.jpg", f) };
HttpMethodParams params = filePost.getParams();
filePost.setRequestEntity(new MultipartRequestEntity(parts, params));
HttpClientParams clientParams = new HttpClientParams();
clientParams.setSoTimeout(2000);
clientParams.setConnectionManagerTimeout(2000);
HttpClient client = new HttpClient(clientParams);
client.getParams().setParameter("http.connection.timeout", 2000);
client.getParams().setParameter("http.socket.timeout", 2000);
int status = client.executeMethod(filePost); // HANGING
타임 아웃을 설정을 했지만 로깅을 해보면 client.executeMethod에서 응답을 기다리고 있어서 프로세스가 진행되지 않았습니다.. 그래서 HttpClient4.0으로 컨버팅 시도(고고싱~~)
// HttpClient 4.0 Source
File f = new File("C:\\test\\beauty.jpg");
HttpPost post = new HttpPost("http://127.0.0.1/PushFile");
FileBody fileBody = new FileBody(f);
MultipartEntity reqEntity = new MultipartEntity();
reqEntity.addPart("beauty.jpg", fileBody);
post.setEntity(reqEntity);
HttpClient client = new DefaultHttpClient();
client.getParams().setParameter("http.connection.timeout", 2000);
client.getParams().setParameter("http.socket.timeout", 2000);
HttpResponse response = client.execute(post);
일단 변환은 완료했습니다. FileEntry를 써야 하나 해서 일단 쓰고 테스트를 진행하니 출력이 안돼서apache 샘플 코드를 보고 수정 했습니다. [SAMPLE]
이렇게 변경을 하면 처음에 LOCK걸리는 현상이 동일하게 발생됩니다. 그래서 별도의 쓰레드를 사용해서 LOCK 을 해제해봤습니다.[완전허접]
/**
* {@link HttpClient} 객체가 응답을 받기 위해 2초 이상
* 대기를 하면 강제로 종료한다.
* @author CoozPlz
*
*/
public class HttpClientAbortWorker extends Thread{
Logger logger = Logger.getLogger(HttpClientAbortWorker.class);
/** 소멸시킬 클라이언트 */
HttpClient client;
public HttpClientAbortWorker(HttpClient client) {
super();
this.client = client;
}
public void run() {
try {
/*
* 2초간 대기 합니다.
* 이미지 전송하는 쓰레드는 돌고 있기 정상적인 케이스에는
* 클라이언트가 정상적으로 종료됩니다.
*/
Thread.sleep(2000);
} catch (InterruptedException e) {
}
if(client != null) {
try {
// client 객체를 종료합니다.
client.getConnectionManager().shutdown();
} catch (Exception e) {
}
}
}
}
이제 LOCK을 해제하는 메소드를 추가한 쓰레드를 생성했습니다. 그렇게 되면 원본 코드에 추가를 하겠습니다.
// execute를 하기전에 쓰레드를 동작시킨다.
new HttpClientAbortWorker(client).start();
HttpResponse response = client.execute(post);
이렇게 하면 InterruptedIOException 이 발생됩니다. 예외가 발생되는데 어찌나 기쁘던지..ㅋㅋ
조금 더 확인 해본 결과 예외가 발생 안될 때도 있네요. -_-