Java代理不向浏览器发送任何内容

时间:2017-03-30 16:37:52

标签: java multithreading sockets proxy stream

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

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

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

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

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

    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. */
        }
    }
    

    }

1 个答案:

答案 0 :(得分:1)

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

  1. 从下游客户端读取一行行,以确定连接到上游的用户,而不进行缓冲。
  2. 连接上游。
  3. 如果(2)失败,请向下游发送适当的HTTP响应并关闭连接。
  4. 否则,开始双向同时复制字节
  5. 你应该尝试组装整个请求,甚至是标题,并且上面的“字节”和“同时”这两个词是至关重要的。请注意,您不必对HTTP保持活动,for(i in seq_along(data)){ Hmisc::label(data[, i]) <- var.labels[i] } label(data) #> age sex #> "Age in Years" "Sex of the participant" 标头,HTTPS等执行任何操作。