2

突き出た「A」の非有限ストリームを返すサーバーに接続します。すなわち:これ

$ nc 1.2.3.4 9001
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA^C

Apache httpコンポーネントライブラリは、サーバーから応答全体を取得してから解析するようです。JVMがクラッシュしないようにサイズを制限する方法は?

これは私のコードです:

流暢なAPI付き:

public static void main(String[] args) throws ClientProtocolException, IOException {
    Request.Get(url).execute().discardContent();
}

低レベルAPI付き:

public static void main(String[] args) throws ClientProtocolException, IOException {
    String url = "http://1.2.3.4:9001/";
    DefaultHttpClient httpclient = new DefaultHttpClient();
    System.out.println("A");
    HttpGet request = new HttpGet(url);
    System.out.println("B");
    HttpResponse hr = httpclient.execute(request);
    System.out.println("C");
}

私にこれを取得します:

A
B
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at org.apache.http.util.ByteArrayBuffer.expand(ByteArrayBuffer.java:62)
    at org.apache.http.util.ByteArrayBuffer.append(ByteArrayBuffer.java:92)
    at org.apache.http.impl.io.AbstractSessionInputBuffer.readLine(AbstractSessionInputBuffer.java:278)
    at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:92)
    at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:62)
    at org.apache.http.impl.io.AbstractMessageParser.parse(AbstractMessageParser.java:254)
    at org.apache.http.impl.AbstractHttpClientConnection.receiveResponseHeader(AbstractHttpClientConnection.java:289)
    at org.apache.http.impl.conn.DefaultClientConnection.receiveResponseHeader(DefaultClientConnection.java:252)
    at org.apache.http.impl.conn.ManagedClientConnectionImpl.receiveResponseHeader(ManagedClientConnectionImpl.java:191)
    at org.apache.http.protocol.HttpRequestExecutor.doReceiveResponse(HttpRequestExecutor.java:300)
    at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:127)
    at org.apache.http.impl.client.DefaultRequestDirector.tryExecute(DefaultRequestDirector.java:712)
    at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:517)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:906)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:805)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:784)
    at com.dudebro.WhatHappen.main(WhatHappen.java:103)

関連する質問は無関係であることに注意してください。APIに応答本文を要求することすらしませんが、それでもクラッシュします。

4

2 に答える 2

4

次のパラメータを設定してみてください。

MAX_LINE_LENGTH = "http.connection.max-line-length"
MAX_HEADER_COUNT = "http.connection.max-header-count"

最初のもののデフォルトは-1で、これは制限がないことを意味すると思います。

于 2013-01-29T20:34:30.697 に答える
1

スタックトレースから明らかなことですBufferedReader.readLine()。JVMがメモリを使い果たすまで、応答ステータスラインの解析を開始するラインターミネータが見つからないため、バッファを増やし続けます。コードをブロックにラップしてtryキャッチOutOfMemoryErrorしたり、Apacheメンテナにパッチを送信したりすることもできますが、実際のアプリケーションではこの問題を実際に考慮に入れるべきではないと思います。

「A」の無限ストリームは確実に有効なHTTP応答ステータスラインではないため、そのサーバーはHTTPに準拠していません。通常、サーバーは、受け入れるものに対して寛大で、送信するものに対して厳密になるように設計されています。つまり、非準拠のクライアントが実際に存在する可能性があることを考慮に入れる必要があります。

一方、クライアント開発者は、サーバーが適切に実装されていると想定することがよくあります。そうでない場合、サーバーを実行している企業はクライアントを取得できません...

この場合、ターゲットサーバーはプロトコルに準拠していないため、価値のあるサービスを提供していないことは明らかです。そのため、誰もサーバーから何も取得できず、Googleはインデックスを作成できません。そのため、誰がパブリックURLをそのようなアプリケーション?サーバープログラムが機能していないことを通知するため、開発マシンでクライアントがクラッシュしても問題ないと思います。自分で管理している場合は修正できます。そうでない場合は、サービスプロバイダーを切り替えます。繰り返しになりますが、これは現実の世界では起こりません。そのような悪いサービスはすべてのクライアントをクラッシュさせ、誰もそれを使用しないからです。

コメントで、ユーザーが送信したURLを受け入れるのはサーバーアプリケーションだとおっしゃいました。その場合、悪意のあるユーザーがサーバーをダウンさせないように、実際には行の長さに制限を設定する必要があります。

于 2013-01-29T20:26:06.670 に答える