0

我目前正在实现一个网络代理,但我遇到了一个问题。我可以从浏览器解析我的请求并发出一个新请求,但我似乎有响应问题。它一直挂在我的响应循环中

    serveroutput.write(request.getFullRequest());
            //  serveroutput.newLine();
                serveroutput.flush();
                //serveroutput.
                 //serveroutput.close();
            } catch (IOException e) {
                System.out.println("Writting tothe server was unsuccesful");
                e.printStackTrace();
            }
            System.out.println("Write was succesful...");
             System.out.println("flushed.");

             try {
                 System.out.println("Getting a response...");
                 response= new    HttpResponse(serversocket.getInputStream());
        } catch (IOException e) {
                System.out.println("tried to read response from server but failed");
                e.printStackTrace();
            }

              System.out.println("Response was succesfull");



      //response code

        public HttpResponse(InputStream input) {
    busy=true;

      reader = new BufferedReader(new InputStreamReader(input));
      try {
          while (!reader.ready());//wait for initialization.

          String line;
          while ((line = reader.readLine()) != null) {
              fullResponse += "\r\n" + line;


          }

          reader.close();
          fullResponse = "\r\n" + fullResponse.trim() + "\r\n\r\n";
      } catch (IOException`` e) {

          e.printStackTrace();
      } 
      busy = false;
  }
4

3 回答 3

2

您正在对套接字进行阻塞同步读取。Web 服务器在向您发送页面后不会关闭它们的连接(如果指定了 HTTP/1.1),因此它将坐在那里并阻塞,直到 Web 服务器超时连接。要正确执行此操作,您需要查找Content-Length标题并在到达正文时读取适当数量的数据。

您真的不应该尝试重新发明轮子,而是使用提供的核心 JavaHttpURLConnection或 AppacheHttpClient来提出您的请求。

于 2013-02-13T00:32:38.977 回答
1

你在这里犯了很多错误。

  • 使用自旋循环调用ready()而不是仅仅在后续读取中阻塞。
  • Reader当您不知道数据是文本时使用。
  • 甚至没有实现 HTTP 1.1 协议。

我建议您不要查看您的代码,而是查看HTTP 1.1 RFC。为 HTTP 1.1 实现一个简单的代理所需要做的就是:

  1. 从客户端读取一行。这应该是一个 CONNECT 命令,命名您要连接的主机。使用 DataInputStream 而不是 BufferedReader 读取此内容,是的,我知道它已被弃用。

  2. 连接到目标。如果成功,则将 HTTP 200 发送回客户端。如果没有,发送任何适当的 HTTP 状态并关闭客户端。

  3. 如果在 (2) 处成功,则启动两个线程,一个将所有数据从客户端复制到目标,以字节为单位,另一个执行相反的操作。

  4. 当您让 EOS 读取其中一只袜子时,请调用shutdownOutput()另一只。

  5. 如果shutdownOutput()尚未在该线程的输入套接字上调用,则退出该线程。

  6. 如果它已经被调用,关闭两个套接字并退出线程。

请注意,除了 CONNECT 命令,您无需解析任何内容;您不必担心内容长度;您只需要正确传输字节,然后正确传输 EOS。

于 2013-02-13T02:36:02.220 回答
1
while (!reader.ready());

这一行进入一个无限循环,使 CPU 抖动,直到流可供读取。通常不是一个好主意。

于 2013-02-13T00:29:23.717 回答