如何保持HttpClient连接保持活跃?

时间:2012-12-03 04:45:02

标签: java android http http-post httpclient

我正在使用HttpClient POST方法。我需要创建一次HttpClient,并且应该使用Keep Alive Connection。但我认为在我的情况下,它每次都建立一个新的连接。

所以,我需要为HttpClient使用 Keep Alive 连接。

这是我的代码片段,任何帮助都会得到很多赞赏。

ClientConnectionManager mgr = httpclient_recv.getConnectionManager();
    hp = httpclient_recv.getParams();
    httpclient_recv = new DefaultHttpClient(
    new ThreadSafeClientConnManager(hp,mgr.getSchemeRegistry()), hp);

    while (true) {

        try {

            java.util.logging.Logger.getLogger("org.apache.http.wire")
                    .setLevel(java.util.logging.Level.FINER);
            java.util.logging.Logger.getLogger("org.apache.http.headers")
                    .setLevel(java.util.logging.Level.FINER);

            System.setProperty("org.apache.commons.logging.Log",
                    "org.apache.commons.logging.impl.SimpleLog");
            System.setProperty(
                    "org.apache.commons.logging.simplelog.showdatetime",
                    "true");
            System.setProperty(
                    "org.apache.commons.logging.simplelog.log.httpclient.wire",
                    "debug");
            System.setProperty(
                    "org.apache.commons.logging.simplelog.log.org.apache.http",
                    "debug");
            System.setProperty(
                    "org.apache.commons.logging.simplelog.log.org.apache.http.headers",
                    "debug");

            ByteArrayEntity bae = new ByteArrayEntity(byteData);
            bae.setContentType(new BasicHeader(HTTP.CONTENT_TYPE,
                    "binary/octet-stream"));

            httppost_recv.setHeader(HTTP.CONN_DIRECTIVE,HTTP.CONN_KEEP_ALIVE);
            httppost_recv.setEntity(bae);



            {
                System.out.println("res b4 response");
                 response_recv = httpclient_recv
                        .execute(httppost_recv);
                 response_recv.getEntity().consumeContent();
                System.out.println("res a4 response");
                if (response_recv != null) {
                    byteArray = EntityUtils.toByteArray(response_recv
                            .getEntity());
                    playing  = true;
                }
                        }
                 }

以及logcat日志是:

12-03 10:07:29.466: I/System.out(1529): res b4 response
12-03 10:07:29.646: D/org.apache.http.wire(1529): >> "POST /ping HTTP/1.1[EOL]"
12-03 10:07:29.666: D/org.apache.http.wire(1529): >> "Connection: Keep-Alive[EOL]"
12-03 10:07:29.686: D/org.apache.http.wire(1529): >> "Content-Length: 1[EOL]"
12-03 10:07:29.705: D/org.apache.http.wire(1529): >> "Content-Type: binary/octet-stream[EOL]"
12-03 10:07:29.716: D/org.apache.http.wire(1529): >> "Host: 192.168.1.36[EOL]"
12-03 10:07:29.725: D/org.apache.http.wire(1529): >> "User-Agent: Apache-HttpClient/UNAVAILABLE (java 1.4)[EOL]"
12-03 10:07:29.736: D/org.apache.http.wire(1529): >> "[EOL]"
12-03 10:07:29.746: D/org.apache.http.headers(1529): >> POST /ping HTTP/1.1
12-03 10:07:29.746: D/org.apache.http.headers(1529): >> Connection: Keep-Alive
12-03 10:07:29.756: D/org.apache.http.headers(1529): >> Content-Length: 1
12-03 10:07:29.756: D/org.apache.http.headers(1529): >> Content-Type: binary/octet-stream
12-03 10:07:29.765: D/org.apache.http.headers(1529): >> Host: 192.168.1.36
12-03 10:07:29.765: D/org.apache.http.headers(1529): >> User-Agent: Apache-HttpClient/UNAVAILABLE (java 1.4)
12-03 10:07:29.776: D/org.apache.http.wire(1529): >> "[0x0]"
12-03 10:07:29.796: D/org.apache.http.wire(1529): << "HTTP/1.1 200 OK[EOL]"
12-03 10:07:29.805: D/org.apache.http.wire(1529): << "Server: gSOAP/2.8[EOL]"
12-03 10:07:29.816: D/org.apache.http.wire(1529): << "Content-Type: binary/octet-stream[EOL]"
12-03 10:07:29.826: D/org.apache.http.wire(1529): << "Content-Length: 2048[EOL]"
12-03 10:07:29.836: D/org.apache.http.wire(1529): << **"Connection: close[EOL]"**
12-03 10:07:29.887: D/org.apache.http.headers(1529): << HTTP/1.1 200 OK
12-03 10:07:29.896: D/org.apache.http.headers(1529): << Server: gSOAP/2.8
12-03 10:07:29.896: D/org.apache.http.headers(1529): << Content-Type: binary/octet-stream
12-03 10:07:29.906: D/org.apache.http.headers(1529): << Content-Length: 2048
12-03 10:07:29.906: D/org.apache.http.headers(1529): << **Connection: close**
12-03 10:07:29.916: I/System.out(1529): res a4 response

3 个答案:

答案 0 :(得分:8)

  

10:07:29.746:D / org.apache.http.headers(1529):&gt;&gt;连接:Keep-Alive

您正在请求keepalive。

  

10:07:29.836:D / org.apache.http.wire(1529):&lt;&lt; “连接:关闭[EOL]”

服务器拒绝它。

你最终无法做到这一点。

答案 1 :(得分:3)

从HTTP 1.1开始,默认情况下启用keep-alive。如果您不希望在处理HTTP 1.1时明确重用连接,则需要关闭连接。

对于1.0,标题就是你为此设置的标题&#34; Connection:Keep-alive&#34; 这只会暗示您要重用连接的服务器。当处于压力或其他原因时,服务器可能会选择采取不同的行动,如下所述。

对于大多数用途,这里的大多数答案都是正确的,在哪里添加keep alive标头并且效果很好。以下说明适用于您执行此操作但仍无效的情况。

服务器端发布

通常,当服务器正常运行时,答案将集中在设置上,但这并非完全正确。服务器(如Rudra)构建为在不同情况下表现不同。保持活动状态伴随着服务器在断开连接之前为您提供的许多请求,这也是为了向其他人提供服务,因此在高负载的情况下,某些服务器可能会采取减少保持活动请求的数量为每个新连接服务。

从上次收到的请求中还有一个超时设置,如果在该时间窗口中没有进一步的请求,最终会导致断开连接。很少有现代服务器可以根据他们目前的容量改变这一点,或者在恐慌情况下将其降低到0,使得保持活力毫无意义。因此,如果您尝试连接的服务器遇到任何此类(竞赛,恐慌)情况,它可能会选择放弃您的请求。

客户端发布

出于文档目的。 来自hc.apache.org

  

HttpClient始终尽力重用连接。连接   默认情况下启用持久性,无需配置。下   在某些情况下,这可能导致连接泄漏,从而丢失   资源。禁用连接持久性的最简单方法是   提供或扩展强制关闭连接的连接管理器   在releaseConnection方法中发布。

HttpClient提供了这些(读取:琐碎的)开箱即用的东西。但是,Apache还提供了其他可以添加的功能,以提高它的性能。

例如,可以为HttpClient定制ConnectionManager。

因此,可以阻止保持活动/连接持久性的事情是您可能正在使用的连接管理器(在您的情况下这不是真的,但在其他几种情况下可能也是如此)。如果您从某个API获取Client对象以进行调用,那么这可能是一个完全未知/抽象的事实。下面列出了一个如何自定义的示例(来自Apache连接管理文档)

PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
// Increase max total connection to 200
cm.setMaxTotal(200);
// Increase default max connection per route to 20
cm.setDefaultMaxPerRoute(20);
// Increase max connections for localhost:80 to 50
HttpHost localhost = new HttpHost("locahost", 80);
cm.setMaxPerRoute(new HttpRoute(localhost), 50);

CloseableHttpClient httpClient = HttpClients.custom()
    .setConnectionManager(cm)
    .build();

(有关详细信息,请参阅Apache documentation on connection management

如果遇到此问题,请在没有CM的情况下试用或创建自己的HttpClient对象。也没有必要将CM用于多个连接。内置的CM足够公平。如果您发现性能下降,可以编写自己的连接管理器。

然而,在你的情况下,你的服务器不是非常支持它可能根本不尊重Keep-alive,即使你有那些标题,什么不是。您需要检查超时标头作为响应,在向服务器发送新请求时发送保持活动以确定服务器是否投诉。

答案 2 :(得分:0)

为什么不用你所有的请求使用同一个客户端???

我一直在开发一个需要向很多网络服务请求大量数据的应用程序,为此我只使用一个静态客户端并且工作正常!

我创建了一个返回HttpClient的类和另一个管理我所有请求的类(POST和GET),很简单;)