Java 中的代理输入/输出流问题

发布于 2024-10-15 17:08:37 字数 2428 浏览 3 评论 0原文

一段时间以来,我一直在尝试一些不同的方法来让我的自定义代理正常工作,到目前为止我能够做到的唯一方法是使用 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 确实会打印“reading”,但永远不会超过 read() 部分。

感谢您的任何建议!

I've been trying for a while a few different methods to get my custom proxy to work, and the only way I've been able to so far is through use of Apache's HttpClient. However, for the sake of knowing, I was wondering why I'm having trouble with my own proxy handle implementation below:


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);
        }
    }

In a nutshell (and disregarding my request header parsing flaws), the above code compiles and runs, however, the inToOut() method seems to struggle a bit and lock up during the input.read(), and I'm not too sure why. I do know as a fact that the original socket I'm passing in is valid and opened without errors. Additionally, the System.out in the inToOut() function does print "reading" but never gets past the read() portion.

Thank you for any suggestions!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

悲欢浪云 2024-10-22 17:08:37

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

This is no way to write a proxy. In the case of HTTP you only have to process the first line, that tells you the target host. Everything else is just copying bytes back and forth, subject to a couple of minor refinements such as reporting upstream connect errors correctly snd handling shutdowns properly. The FTP case is trickier and should be handled completely separately, but again once you get past the connect phase it's just copying bytes around. The less effortmyou make to understand the protocol the simpler and better it gets.

小猫一只 2024-10-22 17:08:37

在您的 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() 并且它工作正常(它实际上帮助我解决了我遇到的类似问题- 谢谢)

In your sendAndReceive function, perhaps try using DataInputStream and 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();
}

The problem doesn't seem to be in the inToOut function - I've tried using inToOut() and it works fine (it actually helped me fix a problem I was having with something similar - Thanks)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文