2010-03-08 1 views
0

자카르타 커먼즈 HttpClient에 문제가 있습니다. 내 스스로 작성한 HttpServer가 실제 요청을 받기 전에 하나의 요청이 완전히 비어 있습니다. 그것이 첫 번째 문제입니다. 첫 번째 문제가 해결되었습니다. 그것은 불필요한 URLConnection에 의한 것입니다! 번째 문제 때때로 요청 데이터가 HTTP 요청의 제 3 또는 제 4 라인 이후 끝난다 디버깅에 Jakarta Commons HttpClient에서 빈 요청을받는 이유는 무엇입니까?

POST/HTTP/1.1 
User-Agent: Jakarta Commons-HttpClient/3.1 
Host: 127.0.0.1:4232 

내가 축 TCPMonitor를 사용하고 있습니다. 거기에는 모든 일이 잘되지만 빈 요청이 있습니다. 스트림을 처리 할 수있는 새로운 방법을 찾을 수

StringBuffer requestBuffer = new StringBuffer(); 

InputStreamReader is = new InputStreamReader(socket.getInputStream(), "UTF-8"); 

int byteIn = -1; 
do { 
    byteIn = is.read(); 
    if (byteIn > 0) { 
     requestBuffer.append((char) byteIn); 
    } 
} while (byteIn != -1 && is.ready()); 

String requestData = requestBuffer.toString(); 

:

어떻게 스트림을 처리합니다. 나는 모든 헤더 매개 변수를 읽고 'content-length'를 사용하여 게시물 데이터를 읽습니다.

client.getParams().setSoTimeout(30000); 

method = new PostMethod(url.getPath()); 
method.getParams().setContentCharset("utf-8"); 
method.setRequestHeader("Content-Type", "application/xml; charset=utf-8"); 
method.addRequestHeader("Connection", "close"); 
method.setFollowRedirects(false); 

byte[] requestXml = getRequestXml(); 

method.setRequestEntity(new InputStreamRequestEntity(new ByteArrayInputStream(requestXml))); 

client.executeMethod(method); 

int statusCode = method.getStatusCode(); 

당신의 사람에게 어떻게 이러한 문제 문제를 해결하는 아이디어 유무 : 내가 요청을 보내는 방법

InputStream is = mySocket.getInputStream(); 
if (is == null) { 
    return; 
} 
BufferedReader in = new BufferedReader(new InputStreamReader(is, "UTF-8")); 

// Read the request line 
// ... 
// ... 

// Parse the header 
Properties header = new Properties(); 
if (st.hasMoreTokens()) { 
    String line = in.readLine(); 
    while (line != null && line.trim().length() > 0) { 
     int p = line.indexOf(':'); 
     header.put(line.substring(0, p).trim().toLowerCase(), line.substring(p + 1).trim()); 
     line = in.readLine(); 
    } 
} 

// If the method is POST, there may be parameters 
// in data section, too, read it: 
String postLine = ""; 
if (method.equalsIgnoreCase("POST")) { 
    long size = 0x7FFFFFFFFFFFFFFFl; 
    String contentLength = header.getProperty("content-length"); 
    if (contentLength != null) { 
     try { 
      size = Integer.parseInt(contentLength); 
     } catch (NumberFormatException ex) { 
     } 
    } 
    postLine = ""; 
    char buf[] = new char[512]; 
    int read = in.read(buf); 
    while (read >= 0 && size > 0 && !postLine.endsWith("\r\n")) { 
     size -= read; 
     postLine += String.valueOf(buf, 0, read); 
     if (size > 0) { 
      read = in.read(buf); 
     } 
    } 
    postLine = postLine.trim(); 
    decodeParms(postLine, parms); 
} 

?

알렉스

내가 처음 문제에 대해 잘 모르지만, 내가 두 번째 문제는이 때문입니다 생각

답변

1

while 루프의 두 번째 조건과 관련이있을 수 있습니다. isReady() 메서드는 다음 읽기가 차단 될 때 false를 반환 할 수 있지만 차단 여부에 상관하지 않으므로 간단하게 처리 할 수 ​​있습니다. 그것을 제거하십시오 (당신은 더 많은 것을 여기에서 읽을 수있다 : http://java.sun.com/j2se/1.5.0/docs/api/java/io/InputStreamReader.html#ready%28%29). 다음으로 변경해보십시오.

byte[] buf = new byte[500]; 
while((is.read(buf))>-1){ 
    requestBuffer.append(new String(buf).trim()); 
    buf = new byte[500]; 
} 

이제 전체 요청을 받아야합니다.

+0

is.ready()를 제거하면 읽기 시간이 너무 길어집니다. 응답이 돌아올 때까지 약 20 초가 걸립니다. – alexvetter

+0

'응답이 돌아 왔습니다'이라고 말하면 requestbuffer에 요청 XML을 읽는 데 20 초가 걸립니까? – simonlord

+0

전체 요청은 xml 요청을 읽고 응답을 보내는 데 20 초 정도 걸립니다. – alexvetter

1

: 보낸 사람이 빨리하지

} while (byteIn != -1 && is.ready()); 

경우 충분한 데이터를 전송, 수신 다음 패킷이 전송되기 전에 is.ready()으로 전화 할 수 있습니다. 이로 인해 is.ready()false을 반환하므로 루프가 중지됩니다.

} while (byteIn != -1); 

편집

하지만 실제로는, 당신은 @ simonlord의 대답의 라인을 따라 방법을 다시 작성해야합니다

최소한의 수정으로 그 라인을 변경하는 것입니다. 한 번에 1 바이트 씩 비 버퍼링 된 스트림을 읽는 것은 정말 나쁜 생각입니다. 각 read 호출에 대해 시스템 호출을 수행하게되는데, 이는 대단히 비효율적입니다. 당신은 HTTP 프로토콜에 적절한주의를 지불하지 않았기 때문에

편집 2

제거 is.ready() 지연이 발생하는 이유입니다. 문제는 HttpClient 코드가 TCP 연결의 요청 측을 열어 두어 연결을 다시 사용할 수있게하는 것이 었습니다. 간단한 (그러나 최적이 아닌) 솔루션은 HttpClient가 연결 요청 측을 닫도록 구성했을 것입니다. 그러면 코드가 EOF를 바로 보았을 것입니다. 실제로 한 것은 다른 해결책이었습니다.

전체 HTTP 사양을 깊이있게 이해하고 충실하게 구현할 준비가되어 있지 않으면으로 서버 측 HTTP 프로토콜을 구현하려고하지 마십시오. 기존 구현은 사용자가 함께 쓸 수있는 것보다 더 빠르고 신뢰할 수 있습니다. 스펙의 서브 세트를 구현할 때의 문제점은 서버가 구현/테스트하는 데 신경 쓰지 않는 스펙의 일부를 사용하는 실제 브라우저와 대화해야 할 수도 있다는 것입니다.

+0

is.ready()를 제거하면 읽기 시간이 너무 길어집니다. 응답이 돌아올 때까지 약 20 초가 걸립니다. – alexvetter