HttpClient 上严格可靠的超时

发布于 2025-01-01 05:48:05 字数 1743 浏览 0 评论 0原文

我正在使用 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 中设置超时参数)!

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

谢谢

I'm reading a web page using HttpClient like this:

        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();
        }  

I need a timeout on the entire job (connecting, waiting & reading - All together or separately).
I tried setting timeout parameters just after httpclient = new DefaultHttpClient(); line:

        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);

But it didn't worked (It timeouts after about 10 times more than the timeout I set).
So I tried a thread to cancel request after a time using httpget.abort() & httpclient.getConnectionManager().shutdown() just after httpget = new HttpGet("http://google.com"); line like this:

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

but it had no effect(Timer runs; but those two lines of code do nothing!)!!
I also tried to use this:

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

but it was same as my first try (setting timeout parameters in HttpClient)!!

what is the problem?
How can I solve my timeout problem?

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

浮生未歇 2025-01-08 05:48:05

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

你正在做的事情是正确的。

首先,如果您使用 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值将用于每次连接尝试,因此在最坏的情况下,超时前的总运行时间可以是 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

因此解决此问题的最佳方法是实现一个仅返回一个 IP 地址的自定义 ClientConnectionOperator.resolveHostname 方法。

Not the solution, but more of an explanation of what is going on.

What you are doing is correct.

First of all, if you are using Log4J, make sure you see everything that HttpClient wants to show you:

log4j.logger.org.apache.http=trace

Then take a look at this class:

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

This connection operator is multihome network aware and will attempt to retry failed connects against all known IP addresses sequentially until the connect is successful or all known addresses fail to respond. Please note the same CoreConnectionPNames.CONNECTION_TIMEOUT value will be used for each connection attempt, so in the worst case the total elapsed time before timeout can be CONNECTION_TIMEOUT * n where n is the number of IP addresses of the given host.

That's what most likely is happening in your case.

Also, it is better to use constants from this interface 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"

You need only two of them:

HttpConnectionParams.CONNECTION_TIMEOUT
HttpConnectionParams.SO_TIMEOUT

So the best way to solve this is to implement a custom ClientConnectionOperator.resolveHostname method that returns only one IP address.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文