我必须使用Java套接字来发送和接收HTTP请求(我必须!)。因此,我正在寻找一个考虑content-length
和Transfer-Encoding: chunked
等的解决方案......以确定HTTP请求何时结束。
这是我到目前为止所提出的一个例子:
public String getWebpage()
{
try{
_out.print("GET / HTTP/1.1\r\nHost: www.google.com\r\n\r\n");
_out.flush();
String fullRequest = "";
String line = null;
while (( line = _in.readLine()) != null)
{
fullRequest += line + "\r\n";
if(isFullRequest(fullRequest))
{
System.out.println(fullRequest);
return fullRequest;
}
}
}catch(Exception e){}
return null;
}
private boolean isFullRequest(String request)
{
return request.contains("\r\n\r\n") //Make sure we have the headers
&& request.contains("</html>"); //Make sure we have the html
}
我的isFullRequest()
方法是检测请求结束的一种非常便宜的方法,但不可靠。
我没有重新发明轮子并花费无数个小时进行调试,而是询问Java中已经包含的类或方法是否完全符合我的要求?没有额外的不必要的jar依赖?
答案 0 :(得分:4)
如果您不想使用现有的HTTP库,则仅更容易发出HTTP / 1.0请求,以便您不会获得分块响应(仅为HTTP / 1.1定义了chunked)。也不要使用keep-alive,它是HTTP / 1.1隐含的,而不是HTTP / 1.0。总之,请按照以下方式提出您的要求:
GET /page HTTP/1.0
Host: hostname
然后只需读取响应直到数据结束。由于保持活动默认情况下使用HTTP / 1.0关闭,服务器将在响应完成后关闭连接,并且由于HTTP / 1.0不支持分块,因此您也不必担心这一点。
答案 1 :(得分:0)
您可以使用HttpUrlConnection来阅读分块响应。这样您就不必担心检测到请求的结束。
URL url = new URL(urlStr);
HttpURLConnection uc = (HttpURLConnection)url.openConnection();
InputStream in = uc.getInputStream();
byte[] b=new byte[512*1024];
int len;
OutputStream out = new FileOutputStream(f);
while((len=in.read(b))!=-1){
out.write(b,0,len);
}
out.flush();
out.close();
in.close();
如果您想获得内容长度,可以尝试:
long contentLength = uc.getContentLengthLong()
仅当content-length
标题已知时才会有效。
如果不知道还有另一种方式(虽然不是我最喜欢的......)。只需知道内容长度,就可以阅读一次流。 我在一个项目中使用它,在下载页面内容时必须绘制进度条。
long max = uc.getContentLengthLong();
if(max==-1){
max=0;
if(in.markSupported()){
in.mark(1000000000); //max nb of bytes to be read
while((len=in.read(b))!=-1){
max+=len;
}
in.reset();
}
}