简体   繁体   English

为什么我从Jakarta Commons HttpClient收到空请求?

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

I have a problem with the Jakarta Commons HttpClient. 我在Jakarta Commons HttpClient中遇到问题。 Before my self-written HttpServer gets the real request there is one request which is completely empty. 在我自己写的HttpServer收到真正的请求之前,有一个请求是完全空的。 That's the first problem. 那是第一个问题。 The first problem is solved. 第一个问题解决了。 It was caused by an unnecessary URLConnection! 这是由不必要的URLConnection引起的! The second problem is, sometimes the request data ends after the third or fourth line of the http request: 第二个问题是,有时请求数据在http请求的第三或第四行之后结束:

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

For debugging I am using the Axis TCPMonitor. 为了进行调试,我使用了Axis TCPMonitor。 There every things is fine but the empty request. 那里的一切都很好,但是空的请求。

How I process the stream: 我如何处理流:

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

Found a new way to process the stream. 找到了一种处理流的新方法。 I read all header parameters and use the 'content-length' for reading the post data. 我读取了所有标头参数,并使用“ 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);
}

How I send the request: 我如何发送请求:

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

Have anyone of you an idea how to solve these problems the problem? 你们有谁知道如何解决这些问题的想法吗?

Alex 亚历克斯

I don't know about the first problem, but I think your second problem is due to this: 我不知道第一个问题,但是我认为您的第二个问题是由于以下原因:

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

If the sender is not quick enough sending data, the receiver may call is.ready() before the next packet has been sent. 如果发送方发送数据的速度不够快,则接收方可以在发送下一个数据包之前调用is.ready() This will cause is.ready() to return false which will cause the loop to stop. 这将导致is.ready()返回false ,这将导致循环停止。

The minimal fix is to change that line to: 最小的解决方法是将该行更改为:

} while (byteIn != -1);

EDIT 编辑

But really, you need to rewrite the method along the lines of @simonlord's answer. 但是实际上,您需要按照@simonlord的答案重写方法。 It is a really bad idea to read an unbuffered stream one byte at a time. 一次读取一个字节的无缓冲流是一个非常糟糕的主意。 You end up doing a system call for each read call, which is horribly inefficient. 您最终会为每个read调用进行系统调用,这效率极低。

EDIT 2 编辑2

The reason that removing is.ready() caused delays is because you were not paying proper attention to the HTTP protocol. 删除is.ready()导致延迟的原因是因为您没有适当注意HTTP协议。 The problem was the HttpClient code was keeping the request side of the TCP connection open to allow the connection to be reused. 问题在于HttpClient代码使TCP连接的请求端保持打开状态,以允许连接被重用。 The simple (but sub-optimal) solution would have been to configure HttpClient to close the request side of the connection. 简单(但次优)的解决方案是将HttpClient配置为关闭连接的请求端。 Your code would have then seen the EOF straight away. 您的代码将立即看到EOF。 What you actually did was another solution. 您实际上所做的是另一种解决方案。

Frankly you should not even be trying to implement the server-side HTTP protocol unless you are prepared to understand the entire HTTP specification in depth and implement it faithfully. 坦白地说,除非您准备深入了解整个HTTP规范并如实实现,否则您甚至不应该尝试实现服务器端HTTP协议。 The chances are that an existing implementation will be faster and more reliable than anything that you can knock together. 有可能的是,现有的实现方式将比您可以组合在一起的任何方式更快,更可靠。 The problem with implementing a subset of the spec is that your server may need to talk to a real browser that uses parts of the spec that you haven't bothered to implement / test. 实施规范子集的问题在于,您的服务器可能需要与使用您不费吹灰之力实现/测试的部分规范的真实浏览器对话。

It might be to do with the second condition in your while loop, the isReady() method might return false when the next read might block - but you don't really care if it blocks or not, so we can simply remove it (you can read more here: http://java.sun.com/j2se/1.5.0/docs/api/java/io/InputStreamReader.html#ready%28%29 ). 这可能与while循环中的第二个条件有关,当下一次读取可能阻塞时,isReady()方法可能返回false-但您实际上并不关心它是否阻塞,因此我们可以将其删除(您可以可以在此处了解更多信息: http : //java.sun.com/j2se/1.5.0/docs/api/java/io/InputStreamReader.html#ready%28%29 )。 Try changing to this: 尝试更改为此:

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

Now you should get the whole request. 现在您应该获得整个请求。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Jakarta Commons HTTPClient无法使用php在我的Apache服务器上发送发布请求 - Jakarta commons HTTPClient can't send a post request on my apache server with php 使用Jakarta HttpClient模仿POST网络请求 - Using Jakarta HttpClient to mimic a POST network request 如何将安全性Cookie传递到HttpClient Get请求(Apache Commons) - How to pass security cookies into a HttpClient Get request (Apache Commons) commons httpclient - 将查询字符串参数添加到GET / POST请求 - commons httpclient - Adding query string parameters to GET/POST request 从Commons HttpClient切换到HttpComponents后出现“格式错误的请求”错误 - 'Improperly formatted request' error after switching from Commons HttpClient to HttpComponents 如何获得HttpClient请求的响应代码 - How do I get the response code on an HttpClient request org.apache.commons.httpclient.HttpClient卡在请求上 - org.apache.commons.httpclient.HttpClient stuck on request 使用Apache commons HttpClient时,如何覆盖请求中的“Host”标头 - How can I override the “Host” header in the request when using Apache commons HttpClient 为什么我得到一个空的位图? - Why do i get an empty bitmap? 使用Apache Commons VFS时,为什么我的applet中会出现NoClassDefFoundError? - Why do I get a NoClassDefFoundError in my applet, when using Apache Commons VFS?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM