Java 代理 - 无法接收来自 host/Socket 问题的响应

Java Proxy - Can't receive response from host/Socket issue

我正在编写一个简单的 Java 代理。总体架构已提供给我(方法签名等),这就是 Main class 的外观:

private static Socket clientSocket;
private static ServerSocket client;
private static int myPort;

public static void init(int port) throws IOException {
    client = new ServerSocket(port);
    clientSocket = client.accept();
}
public static void handle(Socket clientSocket) {
    try {
        BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
        HttpRequest httpRequest = new HttpRequest(in);

        String hostname = httpRequest.getHost();
        //443 hardcoded from reading the http headers. 
        //Testing using isitchristmas.com
        Socket serverSocket = new Socket(hostname, 443);
        BufferedReader out = new BufferedReader(new InputStreamReader(serverSocket.getInputStream()));
        HttpResponse httpResponse = new HttpResponse(out);
        serverSocket.close();
    } catch (IOException e) {
        e.printStackTrace();
    }

}
public static void main(String args[]) {
    try {
        myPort = Integer.parseInt(args[0]);
        try {
            System.out.println("Initializing socket...");
            init(myPort);
        } catch (IOException e) {
            System.out.println("[ERROR]: " + e.getMessage());
        }
        handle(clientSocket);
    } catch (Exception e) {
        System.out.println("[ERROR]: " + e.getMessage());
    }
}

但是在读入 HttpResponse 时控制台挂起并且从未完成请求 class:

    public HttpResponse(BufferedReader fromServer) throws IOException {
    String line;
    String statusLine = "";
    // Never goes past here
    while ((line = fromServer.readLine()) != null) {
        if (line.isEmpty()) {
            break;
        }

        if (line.toLowerCase().contains("status")) {
            statusLine = line;
        }

        response.append(line);
    }

    if (!response.toString().isEmpty()) {
        getDataAndHeadersFromResponse(response.toString());
        System.out.println("\n\nHTTP Response:\n");
        System.out.println("Status Line: " + statusLine);
        System.out.println("Header Lines: " + headerLines + "\n\n");
        System.out.println("Data: " + data);
    }

}

我怀疑这与我创建套接字的方式有关...不在 ServerSocket 上调用 close() 会发出 Address already in use: JVM_Bind 异常。我似乎也没有正确获取 serverSocket 参数。正如您现在所知道的,我不是很精通套接字编程。这里有什么问题?

  • 您需要在端口 80 上侦听:作业中没有关于 HTTPS 的内容。
  • 请求body不会在流结束时终止,因为客户端仍然打开套接字来读取响应。
  • 您需要从客户端读取 Content-length header,然后准确读取那么多字节的请求 body。
  • 因此您无法使用 BufferedReader 解决此问题,因为您必须计算字节数,而不是字符数。
  • 将请求发送到服务器后,您真正需要做的就是将响应字节直接从服务器复制到客户端:不是作业。
  • 为了坚持作业所说的内容,您同样必须从服务器读取 Content-Length header,以及所有其他 header 和空白行,以及来自服务器的 content-length 字节的响应,并将它们全部复制到客户端。您可以看到,与仅复制字节相比,这是浪费时间。
  • HTTP 中的行终止符是 \r\n,而不是 \n

作业不足:

  • 指定不可行的 BufferedReader
  • 然后不一致地指定 DataInputStream 从服务器读取
  • 根本没有理由使用 DataInputStreamInputStream 就足够了
  • 未提及 RFC 2616 或其前身或后继者
  • 未指定是 HTTP 1.0 还是 1.1
  • 不多说 'to cache Web pages',仅在第 2 页提及,此后再未提及。

学生应该抱怨。