【问题标题】:Java Proxy is not sending anything back to browserJava 代理没有将任何内容发送回浏览器
【发布时间】:2017-03-30 16:37:52
【问题描述】:

我在 Java 中创建了一个代理服务器,(见下面的代码),问题是,我从网络服务器得到响应,但是我的代理客户端处理客户端(浏览器)之间的连接以及使用代理的服务器端创建套接字后的网络服务器。服务器端创建一个客户端并发送请求和套接字,然后在一个新线程中处理。 我有几个问题:

第一个代码是代理的客户端第二个代码部分是代理的服务器端

  • 在浏览器/代理/网络服务器之间发送数据时应该使用什么类型的流?
  • 在从流中发送和接收时可以使用字符串还是应该使用某种类型的字节数组?

  • 为什么浏览器没有从代理接收到任何东西?因为我可以从控制台打印出来,但是当写入流时,浏览器没有任何反应。

  • 另外,为什么我需要在浏览器中点击两次“enter”才能让代理做出反应?

    public class Client implements Runnable {
    
    private String request;
    private String response;
    private Socket browserSocket;
    
    public Client(String request, Socket browserSocket) {
        this.request = request;
        this.response = "";
        this.browserSocket = browserSocket;
    
    }
    
    
    @Override
    public void run() {
        /* Send request to web server and get the response. */
        this.request = Client.modifyHttpHeader("Connection", "close", this.request);
        String hostName = Client.getHttpHeader("Host", this.request);
        if (!hostName.isEmpty()) {
            try {
                /* Send request to the web-server. */
                Socket socket = new Socket(hostName, 80);
                OutputStreamWriter osw = new OutputStreamWriter(socket.getOutputStream());
                PrintWriter pw = new PrintWriter(osw);
                pw.write(this.request);
                pw.flush();
    
    
                System.out.println("---S:REQUEST---");
                System.out.println(this.request);
                System.out.println("---S:REQUEST---");
    
                /* Receive the response from the web-server. */
                BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                String response = "";
                int tmpData;
                while ((tmpData = br.read()) != -1) {
                    response += (char)tmpData;
                }
                this.response = response;
                socket.close(); /* Close the socket between client-side and web-server. */
    
                /* Send the response back to the browser. */
                OutputStreamWriter oswbrowser = new OutputStreamWriter(this.browserSocket.getOutputStream());
                PrintWriter pwBrowser = new PrintWriter(oswbrowser);
                pwBrowser.write(this.response);
                pwBrowser.flush();
                pwBrowser.close();
    
                this.browserSocket.close(); /* Close the socket between client-side and browser. */
    
                System.out.println("---C:RESPONSE---");
                System.out.println(this.response);
                System.out.println("---C:RESPONSE---");
            } catch (Exception e) {
                System.err.println(e.getMessage());
                e.printStackTrace();
            }
        }
    }
    public String getHttpResponse() {
        return this.response;
    }
    
    /**
     * 
     * @param header
     * The name of the HTTP header. Example: "GET".
     * Note: Header name is case sensitive.
     * @param request
     * The HTTP message.
     * @return
     * On success: The value following the HTTP header ": " (colon and whitespace).
     * On failure: Empty string.
     */
    public static String getHttpHeader(String header, String request) {
    
        int startHeaderIndex = request.indexOf(header) + header.length();
        int endHeaderIndex = request.indexOf('\n', startHeaderIndex);
    
        /* Could not find the searched header. */
        if (startHeaderIndex == -1 || endHeaderIndex == -1)
            return "";
    
        /* Add 2 to remove ':' and ' '(white space). Decrement 1 to exclude '\r' and '\n' */
        return request.substring(startHeaderIndex + 2, endHeaderIndex - 1);
    }
    
    /**
     * 
     * @param header
     * The name of the HTTP header. Example: "Connection"
     * Note: The header is case sensitive.
     * @param value
     * The new value you want to put. Example: "Close"
     * @param request
     * The HTTP message.
     * @return
     * On success: A new HTTP request with the modified header value.
     * On failure: Empty string.
     * 
     */
    public static String modifyHttpHeader(String header, String value, String request) {
        int startHeaderIndex = request.indexOf(header) + header.length();
        int endHeaderIndex = request.indexOf('\n', startHeaderIndex);
    
        /* Could not find the searched header. */
        if (startHeaderIndex == -1 || endHeaderIndex == -1)
            return "";
    
        String newRequest = "";
        /* Copy all characters including ':' and ' ' (whitespace) */
        for (int i = 0; i < startHeaderIndex + 2; i++) {
            newRequest += request.charAt(i);
        }
        newRequest += value;
        newRequest += "\r\n";
        /* Add the rest of the request. */
        for (int i = endHeaderIndex + 1; i < request.length(); i++) {
            newRequest += request.charAt(i);
        }
    
        return newRequest;
    }
    
    }
    
    
    
    
    
    
    
    
    
    
    
     public class Server {
    
    
    public static void main(String[] args) throws Exception{
        /* Receiving and parsing port number from command line arguments. */
        int ssPort = 0;
        if (args.length > 1 || args.length == 0){
            System.err.println("Only one argument allowed; port number (int).");
            System.exit(1);
    
        } else {
            try {
                ssPort = Integer.parseInt(args[0]);
            } catch(NumberFormatException exception) {
                System.err.println("Argument \"" + args[0] + "\" must be a number.");
                System.exit(1);
            }
        }       
        ServerSocket serverSocket = new ServerSocket(ssPort); /* Creating the server socket. */
        System.out.println("Proxy running on port: " + ssPort);
    
        while(true) {
            System.out.println("Waiting for client...");
            Socket clientSocket = serverSocket.accept(); /* Listening for connections. */
            BufferedReader bReader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
            String request = "";
            int tmpData;
            while ((tmpData = bReader.read()) != -1) {
                request += (char)tmpData;
            }
    
            Client clientObject = new Client(request, clientSocket);
            Thread clientThread = new Thread(clientObject);
            clientThread.start(); /* Start the client thread. */
        }
    }
    

    }

【问题讨论】:

    标签: java multithreading sockets proxy stream


    【解决方案1】:

    全部扔掉。这不是代理的编写方式。 HTTP 代理应该:

    1. 从下游客户端读取 一个 行,以确定要连接到上游的谁,而无需缓冲。
    2. 连接上游。
    3. 如果 (2) 失败,则向下游发送适当的 HTTP 响应并关闭连接。
    4. 否则,开始在两个方向同时复制字节

    您不应该尝试组合整个请求,甚至是标头,并且上面的“字节”和“同时”这两个词很重要。请注意,您不必对 HTTP keep-alive、Connection 标头、HTTPS 等做任何事情。

    【讨论】:

    • 你好@EJP,如果我不保存,我该如何进行内容过滤?其次,你会推荐使用什么类型的流?第三,确实有答案为什么它没有向浏览器发送任何内容,或者为什么我必须在浏览器中输入两次 URL 才能发生任何事情?谢谢
    • (1) 我不明白这个问题。保存什么? (2) 输入流和输出流。 (3) 我的全部答案就是答案。你不这样做。您正在编写一个 HTTP 代理,但没有正确实现 HTTP。要么正确地做到这一点,首先要对 RFC 2616 和后续版本有很好的了解,要么按照上面的方法去做。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-10-07
    • 2011-04-19
    • 2018-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-07
    相关资源
    最近更新 更多