2

我正在尝试在 Android 中创建代理,我必须使用 sockets 。我已经阅读了许多教程并提出了以下代码。不幸的是,浏览器似乎没有得到任何数据,一段时间后它显示标准网页,说网页不可用。可能是什么原因?谢谢你的帮助。

        ServerSocket serverSocket = null;
            try {
                serverSocket = new ServerSocket(9902, 0, InetAddress.getByName("localhost"));
            } catch (Exception e) {
                e.printStackTrace();
            }
    if (serverSocket != null) {
                while (!Thread.currentThread().isInterrupted()) {
                    try {
                        Socket socket = serverSocket.accept();
                        new Thread(new RunnableToReadSocketData(socket)).start();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }

private class RunnableToReadSocketData implements Runnable {
        private final Socket clientSocket;

        public RunnableToReadSocketData(Socket socket) {
            this.clientSocket = socket;
        }

        @Override
        public void run() {
            Socket serverSocket = null;
            try {
                InputStream streamFromClient = clientSocket.getInputStream();
                PrintWriter streamToClient = new PrintWriter(clientSocket.getOutputStream());

                StringWriter writer = new StringWriter();
                IOUtils.copy(streamFromClient, writer);
                String requestString = writer.toString();

                int firstSpace = requestString.indexOf(" ");
                int secondSpace = requestString.indexOf(" ", ++firstSpace);

                String url = requestString.substring(firstSpace, secondSpace);
                Uri uri = Uri.parse(url);
                String urlWithoutProtocol = uri.getHost();

                System.out.println("==============Reading Socket==============\n" + clientSocket.toString() + "\n" + requestString);

                serverSocket = new Socket(urlWithoutProtocol, 80);

                PrintWriter streamToServer = new PrintWriter(serverSocket.getOutputStream(), true);
                streamToServer.write(requestString);
                streamToServer.flush();

                InputStream streamFromServer = serverSocket.getInputStream();
                StringWriter writerResponse = new StringWriter();
                IOUtils.copy(streamFromServer, writerResponse);
                String responseString = writerResponse.toString();

                System.out.println("==============RECEIVED==============\n" + serverSocket.toString() + "\n" + responseString);

                streamToClient.write(responseString);
                streamToClient.flush();

                streamToClient.close();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    if (serverSocket != null) {
                        serverSocket.close();
                    }

                    if (clientSocket != null) {
                        clientSocket.close();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
4

2 回答 2

1

你这样做是错误的。处理完 CONNECT 命令后,您需要启动两个线程以通过连接复制字节,每个方向一个。在发送任何内容之前不要尝试阅读整个请求;同上响应。只需在收到字节时复制它们。

当您在一个套接字上读取 EOS 时,关闭另一个套接字以进行输出并退出该线程。如果您已经关闭了从中读取 EOS 的套接字,请关闭两者并退出线程。你需要这个,以防任何一端关闭,以正确传播它。

于 2013-06-07T01:47:09.130 回答
0

我同意前面的。

一般原则是:

  • 客户端连接
  • 开始阅读线程
  • 接收请求
  • 解析目的地
  • 打开套接字到目的地
  • 转发请求

  • 对于目标套接字上的每个读取,在客户端套接字上执行写入

  • 对于客户端套接字上的每个读取,在目标套接字上执行写入
  • 如果任一套接字关闭(错误),则关闭另一个

所以,有两个 InputStream,两个 OutputStream,只是在它们之间传送数据。

于 2013-06-07T21:24:27.467 回答