httpClient:如何检查服务器端是否已关闭连接

时间:2017-01-05 15:32:27

标签: java apache sockets httpclient

我们连接到数据提供程序,并使用HttpClient在无限循环中继续读取XML数据。我们已经在Java代码中设置了连接超时和套接字超时。但是,当在HTTP服务器端关闭连接时,我们的应用程序不会抛出任何异常,只是挂起那里什么都不做。由于这种行为,当服务器启动时,Java代码将不会重新连接。有没有办法看看服务器端是否已经关闭套接字连接?

此外,https://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html提到了如何关闭STALE连接,但它仍然无法解决我们的问题。

非常感谢你!

代码段:

private static final HttpClientConnectionManager CONN_MGR = new BasicHttpClientConnectionManager();

public boolean connectToServer() {
    disconnect();

    CredentialsProvider provider = new BasicCredentialsProvider();
    UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(username, password);
    provider.setCredentials(AuthScope.ANY, credentials);

    RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(15 * 1000)
            .setSocketTimeout(15 * 1000).build();

    HttpClient client = HttpClientBuilder.create().setDefaultCredentialsProvider(provider)
            .setSSLSocketFactory(sslsf)
            .setConnectionManager(CONN_MGR)
            .setDefaultRequestConfig(requestConfig).build();

    HttpGet request = new HttpGet(url);

    try {
        HttpResponse response = client.execute(request);
        in = response.getEntity().getContent();
        reader = new BufferedReader(new InputStreamReader(in));
        connected = true;

        return true;
    } catch (Exception re) {
        LOGGER.error("error", re);
    }

    return false;
}

public void process() {
    String xml = null;
    while (!shuttingDown) {
        try {

            /* if we know the server side closed the connection already here
               we can simply return and scheduler will take care of anything else. */

            xml = reader.readLine();
            lastSeen = System.currentTimeMillis();
            if (StringUtils.isBlank(xml)) {
                continue;
            }
            xml = xml.trim();

            // processing XML here
        } catch (IOException | NullPointerException ie) {
            /* We see SocketTimeoutException relatively often and
             * sometimes NullPointerException in reader.readLine(). */
            if (!shuttingDown) {
                if(!connectToServer()) {
                    break;
                }
            }
        } catch (RuntimeException re) {
            LOGGER.error("other RuntimeException", re);
            break;
        }
    }

    // the scheduler will start another processing.
    disconnect();
}

// called by the scheduler periodically
public boolean isConnected() {
    CONN_MGR.closeExpiredConnections();
    CONN_MGR.closeIdleConnections(15, TimeUnit.SECONDS);
    long now = System.currentTimeMillis();
    if (now - lastSeen > 15000L) {
        LOGGER.info("call disconnect() from isConnected().");
        disconnect();
    }

    return connected;
}

3 个答案:

答案 0 :(得分:0)

我认为在java 1.7中引入了自动资源管理

https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html

清理陈旧的连接已经得到了解决,即使在最坏的情况下,实施提供商也会通过监控连接来仔细处理

Apache HttpClient使用HttpClientConnectionManager和其他实用程序类来完成清除过时连接的工作。

答案 1 :(得分:0)

在最后一个catch块之后为你的清理代码添加一个finally块。

  

终于{             CONN_MGR.shutdown();       }

根据文档,它会关闭连接管理器并释放已分配的资源

答案 2 :(得分:0)

当没有数据进入超过15秒时,我们通过关闭来自另一个线程的连接来避免此问题。更具体地说现在isConnected()方法如下:

// called by the scheduler periodically
public boolean isConnected() {
    long now = System.currentTimeMillis();
    if (now - lastSeen > 15000L) {
        disconnect();
    }

    return connected;
}

当然,读取部分得到 java.net.SocketException:Socket关闭 java.lang.IllegalStateException:发生这种情况时仍然分配连接

在此更改后一切正常。