Java HTTP/HTTPS 客户端,HTTPS 请求上的“连接重置”

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28910223/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 07:01:03  来源:igfitidea点击:

HTTP/HTTPS client, "connection reset" on HTTPS requests

javasocketshttphttps

提问by iamprem

I'm trying to make a simple HTTP/HTTPS client using java. What i have done as of now in my Client.java file is here.

我正在尝试使用 java制作一个简单的HTTP/HTTPS 客户端。到目前为止,我在 Client.java 文件中所做的工作就在这里。

Everything is working good when i try to access www.google.com:80. I'm getting the full HTML content in my response BufferedReader.

当我尝试访问 www.google.com:80 时,一切正常。我在响应 BufferedReader 中获得了完整的 HTML 内容。

But, when i try to access www.google.com:443, there is no data coming through BufferedReader

但是,当我尝试访问 www.google.com:443 时,没有数据通过 BufferedReader

For www.facebook.com:80,

对于 www.facebook.com:80,

HTTP/1.1 302 Found

Also, when i try with www.facebook.com:443, Getting the following error:

另外,当我尝试使用 www.facebook.com:443 时,出现以下错误:

Exception in thread "main" java.net.SocketException: Connection reset

Where am i going wrong? Why am i not able to get any response for the HTTPS sites?

我哪里出错了?为什么我无法获得 HTTPS 站点的任何响应?

public class Client {

    public static void main(String[] args) throws IOException {

        //String host = args[0];
        //int port = Integer.parseInt(args[1]);
        //String path = args[2];

        int port = 80;
        String host = "www.google.com";
        String path = "/";

        //Opening Connection
        Socket clientSocket = new Socket(host, port);
        System.out.println("======================================");
        System.out.println("Connected");
        System.out.println("======================================");

        //Declare a writer to this url
        PrintWriter request = new PrintWriter(clientSocket.getOutputStream(),true);

        //Declare a listener to this url
        BufferedReader response = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));

        //Sending request to the server
        //Building HTTP request header
        request.print("GET "+path+" HTTP/1.1\r\n"); //"+path+"
        request.print("Host: "+host+"\r\n");
        request.print("Connection: close\r\n");
        request.print("\r\n");
        request.flush();

        System.out.println("Request Sent!");
        System.out.println("======================================");

        //Receiving response from server
        String responseLine;
        while ((responseLine = response.readLine()) != null) {
            System.out.println(responseLine);
        }
        System.out.println("======================================"); 
        System.out.println("Response Recieved!!");
        System.out.println("======================================");
        request.close();
        response.close();
        clientSocket.close();
    }
}

采纳答案by Jason C

HTTPS is encrypted; it's HTTP via SSL. You can't just send raw HTTP requests. The server will drop your connection immediately if you start sending data without establishing a secure connection first (hence the connection reset error). You have to establish an SSL connection first. You'd want to use an SSLSocket(via SSLSocketFactory, see also example) instead of a Socketin that case.

HTTPS 是加密的;它是通过 SSL 的 HTTP。您不能只发送原始 HTTP 请求。如果您在没有先建立安全连接的情况下开始发送数据(因此出现连接重置错误),服务器将立即断开您的连接。您必须先建立 SSL 连接。在这种情况下,您可能希望使用SSLSocket(via SSLSocketFactory,另见示例) 而不是 a Socket

It's as simple as changing one line of your code for the HTTPS case (well, three if you count the exception specification and the port number change to 443):

就像为 HTTPS 情况更改一行代码一样简单(好吧,如果算上异常规范并且端口号更改为 443,则为三行):

Socket clientSocket = SSLSocketFactory.getDefault().createSocket(host, port);

Note that clientSocketwill be an instance of SSLSocket(which is derived from Socket) in this case.

请注意,在这种情况下,clientSocket将是SSLSocket(源自Socket)的实例。

However, if you're doing this as part of a larger application (as opposed to just a learning experience), consider existing libraries, such as Apache's HttpClient(which supports HTTPS as well) or the built-in HttpURLConnectionand HttpsURLConnectionif you need something more basic. If you need to embed a server in an application you can use the built-in HttpServeror HttpsServer.

但是,如果你这样做是为更大的应用程序(而不仅仅是一个学习的经验)的一部分,考虑现有库,比如Apache的HttpClient(支持HTTPS以及)或内置的HttpURLConnectionHttpsURLConnection如果你需要更多的东西基本. 如果您需要在应用程序中嵌入服务器,您可以使用内置的HttpServerHttpsServer.

Also issues that EJP mentioned in his comment.

还有 EJP 在他的评论中提到的问题。