【问题标题】:Strict and reliable timeout on HttpClientHttpClient 上严格可靠的超时
【发布时间】:2012-02-23 06:40:52
【问题描述】:

我正在使用这样的 HttpClient 阅读网页:

        httpclient = new DefaultHttpClient();
        httpget = new HttpGet("http://google.com");
        HttpResponse response = httpclient.execute(httpget);
        HttpEntity entity = response.getEntity();
        if (entity != null) {
            InputStream PIS = entity.getContent();
        }  

我需要对整个作业(连接、等待和阅读 - 全部或单独)进行超时。
我尝试在httpclient = new DefaultHttpClient(); 行之后设置超时参数:

        int timeout=10;
        httpclient.getParams().setParameter("http.socket.timeout", timeout * 1000);
        httpclient.getParams().setParameter("http.connection.timeout", timeout * 1000);
        httpclient.getParams().setParameter("http.connection-manager.timeout", new Long(timeout * 1000));
        httpclient.getParams().setParameter("http.protocol.head-body-timeout", timeout * 1000);

但它不起作用(它在我设置的超时时间大约 10 倍后超时)。
所以我尝试使用httpget.abort()httpclient.getConnectionManager().shutdown()httpget = new HttpGet("http://google.com"); 行之后取消请求,如下所示:

        (new Timer()).schedule(new java.util.TimerTask() {
            public void run() {
                httpget.abort();
                httpclient.getConnectionManager().shutdown();
            }
        },10000);

但它没有效果(定时器运行;但是这两行代码什么也没做!)!!
我也试过用这个:

URL url = new URL("http://google.com");
URLConnection con = url.openConnection();
con.setConnectTimeout(10000);
con.setReadTimeout(10000);
InputStream PIS = con.getInputStream();

但这和我的第一次尝试一样(在HttpClient中设置超时参数)!!

有什么问题?
如何解决我的超时问题?

谢谢

【问题讨论】:

  • 这总是让人头疼。见This

标签: java timeout httpclient urlconnection


【解决方案1】:

不是解决方案,而是对正在发生的事情的更多解释。

你所做的是正确的。

首先,如果您使用的是 Log4J,请确保您看到了 HttpClient 想要向您展示的所有内容:

log4j.logger.org.apache.http=trace

那就看看这个类:

http://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/impl/conn/DefaultClientConnectionOperator.html

此连接操作员可识别多宿主网络,将尝试按顺序对所有已知 IP 地址重试失败的连接,直到连接成功或所有已知地址都无法响应。请注意相同的 CoreConnectionPNames.CONNECTION_TIMEOUT value 将用于每次连接尝试,因此在最坏的情况下,超时前的总经过时间可能是 CONNECTION_TIMEOUT * n 其中 n 是给定主机的 IP 地址数。

这就是你的情况最有可能发生的情况。

另外,最好使用这个接口中的常量HttpConnectionParams

SO_TIMEOUT = "http.socket.timeout"
TCP_NODELAY = "http.tcp.nodelay"
SOCKET_BUFFER_SIZE = "http.socket.buffer-size"
SO_LINGER = "http.socket.linger"
SO_REUSEADDR = "http.socket.reuseaddr"
CONNECTION_TIMEOUT = "http.connection.timeout"
STALE_CONNECTION_CHECK = "http.connection.stalecheck"
MAX_LINE_LENGTH = "http.connection.max-line-length"
MAX_HEADER_COUNT = "http.connection.max-header-count"
MIN_CHUNK_LIMIT = "http.connection.min-chunk-limit"

你只需要其中两个:

HttpConnectionParams.CONNECTION_TIMEOUT
HttpConnectionParams.SO_TIMEOUT

所以解决这个问题的最好方法是实现一个自定义的 ClientConnectionOperator.resolveHostname 方法,它只返回一个 IP 地址。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-02
    • 1970-01-01
    • 2011-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多