![](/img/trans.png)
[英]Jakarta commons HTTPClient can't send a post request on my apache server with php
[英]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.