检测HTTP请求的结束(Java套接字)最简单的方法是什么?

检测HTTP请求的结束(Java套接字)最简单的方法是什么?,java,sockets,Java,Sockets,我必须使用Java套接字发送和接收HTTP请求(我必须!)。因此,我正在寻找一种考虑内容长度和传输编码的解决方案:分块,等等。。。决定HTTP请求何时结束 以下是我迄今为止提出的一个例子: public String getWebpage() { try{ _out.print("GET / HTTP/1.1\r\nHost: www.google.com\r\n\r\n"); _out.flush();

我必须使用Java套接字发送和接收HTTP请求(我必须!)。因此,我正在寻找一种考虑
内容长度
传输编码的解决方案:分块
,等等。。。决定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
    }
公共字符串getWebpage()
{
试一试{
_out.print(“GET/HTTP/1.1\r\nHost:www.google.com\r\n\r\n”);
_out.flush();
字符串fullRequest=“”;
字符串行=null;
而((line=_in.readLine())!=null)
{
fullRequest+=行+“\r\n”;
if(isFullRequest(fullRequest))
{
系统输出打印项次(完整请求);
返回完整请求;
}
}            
}捕获(例外e){}
返回null;
}
私有布尔isFullRequest(字符串请求)
{
return request.contains(“\r\n\r\n”)//请确保我们有标头
&&request.contains(“”;//确保我们有html
}
我的
isFullRequest()
方法是检测请求结束的一种非常便宜的方法,但不可靠


我想问的是,Java中是否已经包含了一个类或方法,可以完全满足我的需要,而不是重新发明轮子,花费无数的时间进行调试?没有额外的不必要的jar依赖项?

如果您不想使用现有的HTTP库,那么只发出HTTP/1.0请求就更容易了,这样您就不会得到分块响应(分块仅为HTTP/1.1定义)。也不要使用keep-alive,这在HTTP/1.1中是隐式的,但在HTTP/1.0中不是。总之,您的请求如下所示:

GET /page HTTP/1.0
Host: hostname
然后只需读取响应,直到数据结束。由于HTTP/1.0默认情况下关闭了keep alive,服务器将在响应完成后关闭连接,并且由于HTTP/1.0不支持分块,您也不必担心这一点。

您可以使用它来读取分块响应。这样,您就不必担心检测到请求的结束

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()
只有当
内容长度
标题已知时,它才会起作用

如果不知道,还有另一种方法(虽然不是我最喜欢的…)。只需阅读一次流即可了解内容长度。 我在一个项目中使用了它,在下载页面内容时必须绘制进度条

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

非常感谢。这种方法暂时解决了我的问题,但可能也不太可靠,因为从长远来看,它可能会导致一些问题。。(如果存在HTTP/1.0服务器不兼容或Bot检测或保护等问题)如果您希望看起来和行为更像一个真正的浏览器,那么它要复杂得多,因为您不仅需要支持HTTP/1.1和分块,还需要支持gzip和deflate内容编码。即使这样,由于缺少JavaScript,没有加载CSS、图像、字体等包含的资源,没有发送回cookie等等,也很容易将您的请求与桌面浏览器区分开来。