Java套接字HTTPClient:使用两个输入流

时间:2015-03-06 18:25:13

标签: java sockets inputstream

我是Java的新手,我正在编写一个HTTP客户端,它从URL检索HTML内容并将此响应写入文件。之后,所请求网页的所有图像也应存储在本地。

我编写了一个创建新请求的函数,一个检索HTML文件的函数和一个检索图像的函数。不幸的是,我无法检索图像;它们不会写入并存储在该位置。

我猜问题是我正在使用两种不同的输入流。我应该如何重写我的代码来解决这个问题?我不允许使用我的教师的OpenStream()函数:它必须发生在手动GET请求中。

提前致谢。

private static String createRequest(URL url, String httpCmd,
        boolean version1_1) {
    StringBuilder sb = new StringBuilder();
    sb.append(httpCmd.toUpperCase());
    sb.append(' ');
    String path = url.getPath();
    if (!path.startsWith("/")) {
        path = "/" + path;
    }
    sb.append(path);
    if (version1_1) {
        sb.append(" HTTP/1.1\r\n");
        sb.append("Host: ");
        sb.append(url.getHost());
        sb.append("\r\n");
    } else {
        sb.append(" HTTP/1.0\r\n");
    }
    sb.append("\r\n");
    return sb.toString();
}





public void retrieveFile(String htppCommand, String url, int port,
        String htppversion) throws IOException {

    Socket s = new Socket();

    URL u;
    if (url.startsWith("http://")) {
        u = new URL(url);
    } else {
        u = new URL("http://" + url);
    }

    try {
        s.connect(new InetSocketAddress(u.getHost(), port));
        PrintWriter pw = new PrintWriter(s.getOutputStream(), true);

        DataInputStream in = new DataInputStream(s.getInputStream());
        FileOutputStream out = new FileOutputStream("../output.html");

        byte[] data = new byte[4096];

        pw.print(createRequest(u, htppCommand, true));
        pw.flush();


        int length;
        int imagenumber = 0;

        while ((length = in.read(data)) != -1) {

            System.out.println(new String(data));
            out.write(data, 0, length);

            Document doc = Jsoup.parse(new String(data));
            Elements images = doc
                    .select("img[src~=(?i)\\.(png|jpe?g|gif)]");

            for (Element image : images) {

                imagenumber++;
                retrieveImage(image.attr("src"), s, imagenumber);

            }

        }

        pw.close();
        in.close();
        out.close();

    }
    // Host not found
    catch (UnknownHostException e) {
        if (s != null)
            s.close();
        System.err.println("Host not found: " + url);
        System.exit(1);
        return;
    }

    // ------------------------------------------------------------------------------

    // close the socket
    s.close();

}



public void retrieveImage(String imageurl, Socket s, int imagenumber)
        throws IOException {

    String extension = "";

    // System.out.println(image);
    if (imageurl.contains(".jpg")) {
        extension = ".jpg";

    } else {

        if (imageurl.contains(".png")) {

            extension = ".png";

        }

        else {
            extension = ".gif";

        }
    }

    String path = "../image" + imagenumber + extension;

    URL myurl = new URL(imageurl);

    DataInputStream is = new DataInputStream(s.getInputStream());

    PrintWriter printer = new PrintWriter(s.getOutputStream(), true);
    OutputStream os = new FileOutputStream(path);
    printer.print(createRequest(myurl, "GET", true));
    printer.flush();

    int length = 0;

    byte[] b = new byte[4096];

    while ((length = is.read(b)) != -1) {

        os.write(b, 0, length);

    }

    is.close();
    os.close();

}

1 个答案:

答案 0 :(得分:0)

问题很可能是你试图从第一个请求重用套接字。在经典的请求 - 响应中,您应该在检索响应并为另一个请求创建新套接字后关闭套接字。你可能不想仅仅为了家庭作业而搞乱Keep-Alive连接。为简单起见,每个HTTP请求都应该打开一个新的套接字,因此拥有它自己的InputStream。此外,html页面本身与图像之间的请求之间应该没有区别。

因此对于每个请求:

  • 使用主机/端口打开新套接字
  • 打开输入流并在其中写入请求
  • 通过套接字的输出流
  • 检索响应
  • 关闭输入和输出流
  • 关闭套接字连接

希望有所帮助。