微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

这个Java程序如何工作

如何解决这个Java程序如何工作

这里是使用Java执行HTTP GET请求的程序,它获取HTML文档并将其保存在文本文件中。但是问题是我无法理解这段代码的某些部分。

import java.io.*;
import java.net.*;

public class HTTP {
    public static void main(String[] args) {
        try {
            FileOutputStream to_file = new FileOutputStream("f:\\temp.txt");
            URL url = new
                    URL("http://www.dailygames.com/3dgames.html");
            String protocol = url.getProtocol();
            String host = url.getHost();
            int port = url.getPort();
            if (port == -1) {
                port = 80;
            }


            String filename = url.getFile();
            System.out.println(filename);
            Socket socket = new Socket(host,port);
            InputStream from_server = socket.getInputStream();
            PrintWriter to_server = new PrintWriter(socket.getoutputStream());
            to_server.print("GET" + filename + "\n\n");
            to_server.flush();


            byte[] buffer = new byte[4096];
            int byte_read;

            while ((byte_read = from_server.read(buffer)) != -1) {
                to_file.write(buffer,byte_read);
                System.out.print((char) byte_read);
            }
            socket.close();
            to_file.close();
        } catch (Exception e) {
            e.printstacktrace();
        }
    }
}

为什么我们应该在这里使用PrintWriter

  PrintWriter to_server = new PrintWriter(socket.getoutputStream()); 
    
    to_server.print("GET" + filename +"\n\n"); 

print()函数的用途是什么。当我运行该程序时,我创建了一个文本文件,但给出的错误响应为400,而不是200 OK。如何理解此代码以使其正常工作

这是输出文本文件内容

HTTP/1.1 400 Bad Request
Date: Fri,23 Oct 2020 08:27:26 GMT
Server: Apache
Content-Length: 226
Connection: close
Content-Type: text/html; charset=iso-8859-1

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>400 Bad Request</title>
</head><body>
<h1>Bad Request</h1>
<p>Your browser sent a request that this server Could not understand.<br />
</p>
</body></html>

该程序以哪一行代码将请求发送到服务器。

解决方法

要回答您的问题,

为什么我们应该在这里使用PrintWriter

您还可以在此处使用 BufferedWriter 。但是 PrintWriter 提供了 println()方法来在不同平台上写入换行符,并且 BufferedWriter 需要显示对newLine方法的调用。即 newline()可用于换行。 另外,PrintWriter构造函数可以指定参数以实现自动刷新缓存。

您可以参考此链接https://www.programmersought.com/article/9176292993/,详细说明使用套接字API时两者之间的区别

print()函数的用途是什么

在此程序中,to_server.print("GET" + filename +"\n\n"); print()用于发送标头,或换句话说,将请求字符串打印到输出流 但是,您需要在此处进行一些更改:

  1. 就像@Fred在评论中建议的那样,GET和url之间必须有一个空格
  2. 将协议版本添加到您的请求标头中
  3. 使用println()而不是print()将条目打印到单独的行中。
  4. 将域名添加到请求行

例如,

to_server.println("GET " + filename + " HTTP/1.1");

to_server.println("Host: "+host+"\r\n");

该程序以哪一行代码将请求发送到服务器。

总的来说,您的程序按以下步骤工作,并且对该问题的答案位于步骤2和#3(请参见下面的代码中的注释)

  • 创建与主机和端口的套接字连接,即http://www.dailygames.com和80
  • 通过路径和协议版本(即GET /3dgames.html HTTP / 1.1)将HTTP数据包发送到包含方法,资源的outputstream中
  • 正确阅读和解释回复

这是您如何获得所需回复的方法:

import java.io.*;
import java.net.*;

public class HTTP {

public static void main(String[] args) {
    try {
        FileOutputStream to_file = new FileOutputStream("f:\\temp.txt");
        URL url = new URL("http://www.dailygames.com/3dgames.html");

        String host = url.getHost();
        int port = url.getPort();
        if (port == -1) {
            port = 80;
        }

        String filename = url.getFile();
        System.out.println(filename);

        //Create Connection
        //Open socket to a specific host and port
        Socket socket = new Socket(host,port);

        //Get input and output streams for the socket
        InputStream from_server = socket.getInputStream();
        OutputStream outputStream = socket.getOutputStream();

        // Get response OR Instantiates a new PrintWriter passing in the sockets output stream
        PrintWriter to_server = new PrintWriter(outputStream);

        // Send headers OR Prints the request string to the output stream
        to_server.println("GET " + filename + " HTTP/1.1"); // This is a message sent to the server
        to_server.println("Host: " + host); // As you can see,the domain name is passed to the program as an argument. After connected to the server,it sends the domain name,and reads the response from the server.
        to_server.println("");
        to_server.flush();

        byte[] buffer = new byte[4096];
        int byte_read;

        //Reads & Prints each line of the response OR Reads HTTP response
        while ((byte_read = from_server.read(buffer)) != -1) {
            // Print server's response
            to_file.write(buffer,byte_read);
            System.out.print((char) byte_read);
        }
        socket.close();
        to_file.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
}
}
,

尝试一下

import java.io.*;
import java.net.*;

public class HTTP {
    public static void main(String[] args) {
        try {
            URL url = new URL("http://www.dailygames.com/3dgames.html");
            String host = url.getHost();
            int port = url.getPort();
            if (port == -1) {
                port = 80;
            }

            try (
                    Socket socket = new Socket(host,port);
                    BufferedReader serverReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                    PrintWriter serverWriter = new PrintWriter(socket.getOutputStream(),true);
                    Writer destinationFile = new PrintWriter(new FileOutputStream("f:\\temp.txt"),true)
            ) {
                System.out.println("Connection to [" + host + "] status [" + socket.isConnected() + "]");

                final String request = "GET " + url.getFile() + " HTTP/1.1\r\n" +
                        "Host: " + host + "\r\n" +
                        "Connection: close\r\n" +
                        "\r\n";

                System.out.println("REQ: " + request);
                serverWriter.print(request);
                serverWriter.flush();

                final StringBuilder sb = new StringBuilder();
                String line;
                // Store response to file
                while ((line = serverReader.readLine()) != null) {
                    sb.append(line);
                }
                destinationFile.write(sb.toString());
            }
            System.out.println("Completed");
        } catch (Exception exception) {
            exception.printStackTrace();
        }
    }
}

编辑: 我已经通过添加try-with-resources进行了一些常规的清理工作,因此不会打开任何资源,否则应该在finally语句中进行关闭。

为方便起见,我将流资源包装在高级API读写器中。

原始代码的主要问题是:

  1. 缺少“主机:foo”。
  2. 在末尾添加最后一个换行符。

编辑后,发送到服务器的查询将是:

GET /3dgames.html HTTP/1.1 \r\n
Host: http://www.dailygames.com \r\n
Connection: close \r\n
\r\n

我还按照HTTP规范中的指定明确设置了\ r \ n。 println中的行结尾使用系统属性line.separator,该属性可能不是\ r \ n

更正代码后,它可以工作。但是除了不错的练习外,我还会为HTTP请求而不是Socket(HttpClient / OKHttp / etc)选择更高级别的API

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。