0

現在、Web プロキシを実装していますが、問題が発生しました。ブラウザからのリクエストを解析して新しいリクエストを作成することはできますが、応答に問題があるようです。応答ループ内でハングし続けます。

    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またはAppacheのいずれかを使用HttpClientして要求を行う必要があります。

于 2013-02-13T00:32:38.977 に答える
1
while (!reader.ready());

この行は無限ループに入り、ストリームが読み取り可能になるまでCPUをスラッシングします。一般的には良い考えではありません。

于 2013-02-13T00:29:23.717 に答える
1

あなたはここで多くの間違いを犯しています。

  • ready()後続の読み取りでブロックするだけでなく、スピン ループ呼び出しを使用します。
  • Readerデータがテキストであることがわからない場合にa を使用します。
  • HTTP 1.1 プロトコルを少しでも実装していません。

コードを確認する代わりに、HTTP 1.1 RFCを確認することをお勧めします。HTTP 1.1 の単純なプロキシを実装するために必要なことは、次のとおりです。

  1. クライアントから 1 行を読み取ります。これは、接続先のホストを指定する CONNECT コマンドである必要があります。BufferedReader ではなく、DataInputStream でこれを読んでください。はい、非推奨であることはわかっています。

  2. ターゲットに接続します。成功した場合は、HTTP 200 をクライアントに送り返します。そうでない場合は、適切な HTTP ステータスを送信し、クライアントを閉じます。

  3. (2) で成功した場合は、2 つのスレッドを開始します。1 つはクライアントからターゲットにすべてのデータをバイトとしてコピーするスレッドで、もう 1 つはその逆を行うスレッドです。

  4. EOS がこれらの靴下の 1 つを読み取ったらshutdownOutput()、もう 1 つの靴下を呼び出します。

  5. shutdownOutput()このスレッドの入力ソケットでまだ呼び出されていない場合は、スレッドを終了します。

  6. すでに呼び出されている場合は、両方のソケットを閉じてスレッドを終了します。

CONNECT コマンド以外は解析する必要がないことに注意してください。Content-length について心配する必要はありません。バイトを転送してから EOS を正しく転送するだけです。

于 2013-02-13T02:36:02.220 に答える