当前位置: 首页 > 知识库问答 >
问题:

Apache HttpClient在使用SSL时抛出SocketTimeoutException

谯志诚
2023-03-14

我使用的是Apache httpclient 4.3.6和httpcore 4.3.3(与opensaml 3.3.0捆绑)。我试图通过HTTPS通过代理获取网页,但每次都会收到SocketTimeoutException。HTTP连接工作正常。具体的超时并不重要;它只是需要更长的时间才能以更高的值失败。

示例代码

public class TestGet {
    private static final int TIMEOUT = 7000;

    public static void main(String[] args) throws Exception {
        URL url   = new URL("https://www.google.com");
        URL proxy = new URL("https://myproxy:9090/");
        try {
            String s = get(url, proxy);
            System.out.println(s);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static String get(URL url, URL proxy) throws IOException, URISyntaxException {
        CloseableHttpClient client  = HttpClients.createDefault();
        HttpGet             request = new HttpGet(url.toURI());
        HttpHost            host    = null;

        if (proxy != null) {
            host = new HttpHost(proxy.getHost(), proxy.getPort(), proxy.getProtocol());
        }

        RequestConfig config = RequestConfig.custom()
            .setProxy(host)
            .setConnectionRequestTimeout(TIMEOUT)
            .setConnectTimeout(TIMEOUT)
            .setSocketTimeout(TIMEOUT)
            .build();
        request.setConfig(config);

        try {
            CloseableHttpResponse response = client.execute(request);
            try {
                System.out.println(response.getStatusLine());
                return EntityUtils.toString(response.getEntity());
            } finally {
                response.close();
            }
        } finally {
            client.close();
        }
    }
}

尝试连接到代理时引发异常。堆栈跟踪是

org.apache.http.conn.ConnectTimeoutException: Connect to <proxy> failed: Read timed out
    at org.apache.http.impl.conn.HttpClientConnectionOperator.connect(HttpClientConnectionOperator.java:134)
    at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:319)
    at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:371)
    at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:219)
    at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:195)
    at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:86)
    at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:108)
    at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:106)
    at authentication.TestGet.get(TestGet.java:47)
    at authentication.TestGet.main(TestGet.java:22)
Caused by: java.net.SocketTimeoutException: Read timed out
    at java.net.SocketInputStream.socketRead0(Native Method)
    at java.net.SocketInputStream.socketRead(Unknown Source)
    at java.net.SocketInputStream.read(Unknown Source)
    at java.net.SocketInputStream.read(Unknown Source)
    at sun.security.ssl.InputRecord.readFully(Unknown Source)
    at sun.security.ssl.InputRecord.read(Unknown Source)
    at sun.security.ssl.SSLSocketImpl.readRecord(Unknown Source)
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source)
    at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
    at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
    at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:290)
    at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:259)
    at org.apache.http.impl.conn.HttpClientConnectionOperator.connect(HttpClientConnectionOperator.java:125)
    ... 11 more

这看起来很像Apache问题HTTPCLIENT-1478,它与未设置套接字超时有关。这个bug在4.3.4中被标记为已修复(我使用的是4.3.6),虽然一些评论表明在以后的版本中仍然需要解决方法,但它们对我不起作用。更重要的是,我已经进入了SSLConnectionSocketFactory。createConnection()并确认套接字超时设置为非零值。

我卡住了。我不知道连接失败的原因,并且除了调用SSLSocketImpl.startHandshake()进行故障排除之外,我还没有能够更进一步。可能有什么问题,我该如何解决?

共有2个答案

沈栋
2023-03-14

[由提问者回答,可能对他人适用性有限]

确认代理服务器支持HTTPS。即使在到目标服务器的连接上使用了HTTPS,它也可能期望普通的HTTP。如果代理不支持HTTPS,它将不会响应客户端问候消息;从而导致套接字超时。

将< code>javax.net.debug系统属性设置为< code>ssl将启用ssl协商的调试日志记录。如果您看到一个没有后续服务器Hello的ClientHello,代理服务器可能不支持HTTPS。请将代理从< code>https://更改为< code>http://,然后重试。

丰超
2023-03-14

不要使用 .set连接请求超时(超时)

或者,等待很长时间,看看会发生什么。

阅读此以获取更多信息。

 类似资料:
  • 这是我的代码: 我同时从多个线程调用此函数。当我在一次运行中只调用它大约20~30次时,它工作得非常好。但当我在大约2分钟内(对同一个URL)调用它500~600次时,它会抛出 编辑 我尝试只创建一个实例,但它仍然会引发相同的异常

  • 我使用keytool(来自jdk)将mycert.cer文件转换为mycert.jks,并且我正在JMeter的SSL管理器中使用它。将实现设置为Java。当我运行我的脚本时,它弹出JKS密码(输入jks的密码,这是在转换过程中设置的),然后结果显示为“应用程序不可用”(响应代码- 503)。但是我可以看到,应用程序或endpoint没有问题,因为它在Load Runner和postman中工作。

  • 因此,我使用服务器(google-app-engine)在客户端应用程序上进行身份验证。当我使用JavaFX、Webview或HttpsURLConnection时,一切都很好,它们连接起来了,但是当我使用HttpClient时,它会抛出以下错误 javax.net.ssl.sslpeerunverifiedexception:peer未在sun.security.ssl.sslsessionim

  • 我想做的是用httpclient下载一个文件。目前我的代码如下。 我的下载URL如下所示:http://example.com/file/afz938f348dfa3 正如你可以看到没有扩展名的文件(至少在网址)然而,当我去一个正常的浏览器网址,它下载文件asdasdaasda.txt或asdasdasdsd.pdf(名称是不同的url和extenstion并不总是相同的,取决于我试图下载什么)。

  • 方法在什么条件下抛出?官方文件提到: NullPointerException-如果指定的集合包含null元素并且该集合不允许null元素,或者如果指定的集合为null 我如何确保这个“集合不允许空元素” 输出

  • 我有一个嵌套for循环的方法,如下所示: 在我想在'get leaves()'方法中引入之前,这一直很正常。现在,版本将不会编译,因为它说我有一个未报告的,必须捕获或声明要抛出该。我认为这是因为在多个线程上运行。IDE建议的try/catch块组合不能解决此问题。 在Interrupt parallel Stream execution中发布的第二个解决方案表明,我可能可以使用解决这个问题,但我无