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 维护人员提交一个补丁,但我认为您不应该将这个问题真正考虑到实际应用程序中。

该服务器不符合 HTTP 标准,因为“A”的无限流肯定不是有效的 HTTP 响应状态行。通常服务器被设计成对他们接受的内容是自由的,对他们发送的内容是严格的,即他们应该考虑到可能有不合规的客户端进入野外。

另一方面,客户端开发人员通常认为服务器实现得很好,因为如果不是这样,那么运行服务器的业务将不会获得任何客户端......

在这种情况下,很明显目标服务器没有提供任何有价值的服务,因为它甚至不符合协议,所以没有人可以从中获取任何东西,谷歌无法索引它,所以谁会将公共 URL 传播给这样的应用程序?我认为客户端在您的开发机器上崩溃很好,因为它告诉服务器程序不工作。如果它在您的控制之下,您可以修复它,否则您将切换服务提供商。同样,这在现实世界中不会发生,因为如此糟糕的服务会导致其所有客户端崩溃,并且没有人会使用它。

在您所说的评论中,它是一个接受用户提交的 URL 的服务器应用程序。在这种情况下,您应该真正设置行长度限制,以避免恶意用户关闭您的服务器。

于 2013-01-29T20:26:06.670 回答