【问题标题】:Proxy input/output stream issues in JavaJava中的代理输入/输出流问题
【发布时间】:2011-02-01 07:37:44
【问题描述】:

一段时间以来,我一直在尝试几种不同的方法来让我的自定义代理正常工作,到目前为止,我能够做到的唯一方法是使用 Apache 的 HttpClient。但是,为了了解,我想知道为什么我自己的代理句柄实现在下面遇到问题:


public void processProxyRequest (Socket client, String request) throws Exception {

        if ( !request.equals("") ) {

            String[] requestHeaders = request.split("\\r\\n");
            Pattern p = Pattern.compile("([A-Z]*)\\s*([^:\\/]*):\\/\\/([^\\s]*)\\s*(?:HTTP.*)");
            Matcher m = p.matcher(requestHeaders[0]);

            if ( m.matches() ) {
                String method = m.group(1).toUpperCase();
                String proto = m.group(2).toLowerCase();
                String[] requestInfo = m.group(3).split("\\/", 2);

                String host = requestInfo[0];
                host = ( host.split("\\.").length < 3 ) ? "www." + host : host;
                String page = "/";
                if ( requestInfo.length == 2 && !requestInfo[1].equals("") ) {
                    page += requestInfo[1];
                }

                int remotePort = 80;

                if ( proto.equals("https") ) {
                    remotePort = 443;
                }
                else if ( proto.equals("ftp") ) {
                    remotePort = 21;
                }
                this.sendAndReceive(client, request, host, remotePort);
            }
        }

    }

    public void sendAndReceive (Socket client, String request, String host, int port) throws Exception {
        Socket target = new Socket(host, port);
        System.out.println("Connected to server");

        ByteArrayInputStream inStream = new ByteArrayInputStream(request.getBytes());

        this.inToOut(inStream, target.getOutputStream());
        System.out.println("Sent");
        this.inToOut(target.getInputStream(), client.getOutputStream());
        System.out.println("Received");
        target.close();
    }

    public void inToOut (InputStream input, OutputStream output) throws IOException {
        byte[] buffer = new byte[1024]; // Adjust if you want
        int bytesRead;
        System.out.println("reading");
        while ((bytesRead = input.read(buffer)) != -1) {
            output.write(buffer, 0, bytesRead);
        }
    }

简而言之(并且忽略我的请求标头解析缺陷),上面的代码编译并运行,但是,inToOut() 方法似乎有点挣扎并在 input.read() 期间锁定,我不太清楚为什么。我确实知道我传入的原始套接字是有效的并且打开时没有错误。此外,inToOut() 函数中的 System.out 会打印“正在阅读”,但永远不会超过 read() 部分。

感谢您的任何建议!

【问题讨论】:

    标签: java proxy inputstream outputstream


    【解决方案1】:

    这不是写代理的方法。在 HTTP 的情况下,您只需要处理第一行,它会告诉您目标主机。其他一切都只是来回复制字节,需要进行一些小的改进,例如正确报告上游连接错误和正确处理关闭。 FTP 的情况比较棘手,应该完全分开处理,但是一旦你通过了连接阶段,它只是在复制字节。你理解协议的努力越少,它就越简单越好。

    【讨论】:

    • 我明白了,这就是为什么请求行实际上已经传递到 processRequest() 方法开始的原因。我为以后的日志记录功能做了一些额外的解析,而我想跟踪某些请求和响应标头属性。至于来回字节的“简单”复制​​,上面的内容似乎不正确?我相当确定这就是我所做的,将输入流从客户端复制到目标的输出流,然后从目标输入流复制到流中的客户端。然而,仍然没有成功。
    • 不可能在没有看到复制代码的情况下发表评论。除非您使用 NIO,否则每个连接都需要两个线程,每个方向一个复制。当然,两者的代码相同,它们只是在 EOS 之前读取和写入字节。
    • 已经有代码,即inToOut() 方法,它试图将字节从客户端的输入流复制到目标服务器的输出流。当然,我没有将它们都放在单独的线程中,但是刚才我尝试使用线程,然后尝试使用 NIO,但是两次尝试似乎都将数据写入目标服务器(对于我的测试,只是 google.com ) 但在尝试读取响应时它们总是冻结。
    【解决方案2】:

    在你的 sendAndReceive 函数中,也许尝试使用 DataInputStream 和 DataOutputStream

    public void sendAndReceive (Socket client, String request, String host, int port) throws Exception {
        Socket target = new Socket(host, port);
        System.out.println("Connected to server");
    
        this.inToOut(new DataInputStream(client.getInputStream()), new DataOutputStream(target.getOutputStream()));
        System.out.println("Sent");
        this.inToOut(new DataInputStream(target.getInputStream()), new DataOutputStream(client.getOutputStream()));
        System.out.println("Received");
        target.close();
    }
    

    问题似乎不在于 inToOut 函数 - 我尝试使用 inToOut() 并且效果很好(它实际上帮助我解决了我遇到的类似问题 - 谢谢)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-19
      • 2012-11-17
      • 2017-06-09
      • 1970-01-01
      • 1970-01-01
      • 2023-01-20
      相关资源
      最近更新 更多