为什么我会从Jakarta Commons的HttpClient空请求?
-
18-09-2019 - |
题
我与雅加达Commons的HttpClient的问题。 <击>我自写的HttpServer之前得到真正的要求有一个请求,这完全是空的。这是第一个问题。罢工>的的第一个问题就解决了。它是由不必要的URLConnection引起 <击>第二个问题是,有时第三或第四线路的http请求的后请求数据结束:<!/击>
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();
击> <击> 撞击>
<强>实测值来处理流的新方法。我读取所有头参数并使用“内容长度”用于读取后的数据。强>
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说明书和忠实地执行它。有机会,现有的实现会比任何东西,你可以敲起来更快,更可靠。与实施规范的一个子集的问题是,您的服务器可能需要跟使用,你有没有费心去执行/测试规范的部分真正的浏览器。