簡體   English   中英

為什么我從Jakarta Commons HttpClient收到空請求?

[英]Why do I get empty request from the Jakarta Commons HttpClient?

我在Jakarta Commons 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();
 
 
  

找到了一種處理流的新方法。 我讀取了所有標頭參數,並使用“ content-length”讀取了發布數據。

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 (byteIn != -1 && is.ready());

如果發送方發送數據的速度不夠快,則接收方可以在發送下一個數據包之前調用is.ready() 這將導致is.ready()返回false ,這將導致循環停止。

最小的解決方法是將該行更改為:

} while (byteIn != -1);

編輯

但是實際上,您需要按照@simonlord的答案重寫方法。 一次讀取一個字節的無緩沖流是一個非常糟糕的主意。 您最終會為每個read調用進行系統調用,這效率極低。

編輯2

刪除is.ready()導致延遲的原因是因為您沒有適當注意HTTP協議。 問題在於HttpClient代碼使TCP連接的請求端保持打開狀態,以允許連接被重用。 簡單(但次優)的解決方案是將HttpClient配置為關閉連接的請求端。 您的代碼將立即看到EOF。 您實際上所做的是另一種解決方案。

坦白地說,除非您准備深入了解整個HTTP規范並如實實現,否則您甚至不應該嘗試實現服務器端HTTP協議。 有可能的是,現有的實現方式將比您可以組合在一起的任何方式更快,更可靠。 實施規范子集的問題在於,您的服務器可能需要與使用您不費吹灰之力實現/測試的部分規范的真實瀏覽器對話。

這可能與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];
}

現在您應該獲得整個請求。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM