【问题标题】:Java socket HTTPClient: using two inputstreamsJava socket HTTPClient:使用两个输入流
【发布时间】:2015-03-06 18:25:13
【问题描述】:

我是 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();

}

【问题讨论】:

    标签: java sockets inputstream


    【解决方案1】:

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

    所以对于每个请求:

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

    希望对您有所帮助。

    【讨论】:

    • 为什么这么难?使用 Apache HttpClient。
    • @Michael-O 实现 http 客户端是他的任务。
    猜你喜欢
    • 1970-01-01
    • 2020-04-26
    • 2019-07-15
    • 1970-01-01
    • 2010-10-20
    • 2014-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多