문제

자카르타 커먼즈 httpclient에 문제가 있습니다. 자체 작성된 httpserver가 실제 요청을 받기 전에 하나의 요청이 완전히 비어 있습니다. 그것이 첫 번째 문제입니다. 첫 번째 문제는 해결되었습니다. 불필요한 urlconnection으로 인해 발생했습니다! 두 번째 문제는 때때로 요청 데이터가 HTTP 요청의 세 번째 또는 네 번째 줄 다음에 종료된다는 것입니다.

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

디버깅을 위해 Axis 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();

스트림을 처리하는 새로운 방법을 찾았습니다. 모든 헤더 매개 변수를 읽고 게시물 데이터를 읽기 위해 '컨텐츠 길이'를 사용합니다.

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);
}

요청을 보내는 방법 :

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();

이러한 문제를 해결하는 방법을 알고있는 사람이 있습니까?

알렉스

도움이 되었습니까?

해결책

while 루프에서 두 번째 조건과 관련이있을 수 있습니다. 다음 읽기가 차단할 때 isready () 메소드가 거짓을 반환 할 수 있습니다. 그러나 차단 여부에 관계없이 신경 쓰지 않으므로 간단히 제거 할 수 있습니다 (귀하 자세한 내용은 여기에서 읽을 수 있습니다. 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];
}

이제 전체 요청을 가져와야합니다.

다른 팁

첫 번째 문제는 모르지만 두 번째 문제는 다음과 같은 것 같습니다.

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

발신자가 데이터를 충분히 보내지 않으면 수신자가 전화 할 수 있습니다. is.ready() 다음 패킷이 전송되기 전에. 이로 인해 발생합니다 is.ready() 돌려 주다 false 루프가 멈출 것입니다.

최소한의 수정은 해당 라인을 다음으로 변경하는 것입니다.

} while (byteIn != -1);

편집하다

그러나 실제로 @simonlord의 답변을 따라 메소드를 다시 작성해야합니다. 한 번에 한 바이트를 한 바이트로 읽는 것은 정말 나쁜 생각입니다. 당신은 결국 각각에 대한 시스템 호출을 수행하게됩니다 read 끔찍하게 비효율적 인 전화.

편집 2

제거하는 이유 is.ready() 원인 지연은 HTTP 프로토콜에 적절한주의를 기울이지 않았기 때문입니다. 문제는 httpclient 코드가 연결을 재사용 할 수 있도록 TCP 연결의 요청 쪽을 열어 두는 것이 었습니다. 간단한 (그러나 하위 최적) 솔루션은 연결 요청 측면을 닫기 위해 HTTPClient를 구성하는 것이 었습니다. 그러면 코드는 EOF를 곧바로 보았을 것입니다. 당신이 실제로 한 것은 또 다른 해결책이었습니다.

솔직히 당신은 안됩니다 견딜 수 없는 전체 HTTP 사양을 깊이 이해하고 충실하게 구현할 준비가되지 않는 한 서버 측 HTTP 프로토콜을 구현합니다. 기존 구현이 함께 노크 할 수있는 것보다 더 빠르고 신뢰할 수있을 것입니다. 사양의 서브 세트를 구현하는 데있어 문제는 서버가 구현 / 테스트를 귀찮게하지 않은 사양의 일부를 사용하는 실제 브라우저와 대화해야 할 수도 있다는 것입니다.

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