当URL可用时,为什么会发生“java.net.ConnectException:连接超时”异常?

93

我的代码不时地出现ConnectException: Connection timed out。我尝试访问的URL是可以访问的。这段代码对于有些用户有效,但对于有些用户无效。一旦一个用户开始遇到这个异常,他们似乎就会持续遇到这个异常。

以下是堆栈跟踪:

java.net.ConnectException: Connection timed out
Caused by: java.net.ConnectException: Connection timed out
    at java.net.PlainSocketImpl.socketConnect(Native Method)
    at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:333)
    at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:195)
    at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:182)
    at java.net.Socket.connect(Socket.java:516)
    at java.net.Socket.connect(Socket.java:466)
    at sun.net.NetworkClient.doConnect(NetworkClient.java:157)
    at sun.net.www.http.HttpClient.openServer(HttpClient.java:365)
    at sun.net.www.http.HttpClient.openServer(HttpClient.java:477)
    at sun.net.www.http.HttpClient.<init>(HttpClient.java:214)
    at sun.net.www.http.HttpClient.New(HttpClient.java:287)
    at sun.net.www.http.HttpClient.New(HttpClient.java:299)
    at sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(HttpURLConnection.java:796)
    at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:748)
    at sun.net.www.protocol.http.HttpURLConnection.connect(HttpURLConnection.java:673)
    at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:840)

这是我的代码片段:

URLConnection urlConnection = null;
OutputStream outputStream = null;
OutputStreamWriter outputStreamWriter = null;
InputStream inputStream = null;

try {
    URL url = new URL(urlBase);
    urlConnection = url.openConnection();
    urlConnection.setDoOutput(true);

    outputStream = urlConnection.getOutputStream(); // exception occurs on this line
    outputStreamWriter = new OutputStreamWriter(outputStream);
    outputStreamWriter.write(urlString);
    outputStreamWriter.flush();
    inputStream = urlConnection.getInputStream();
    String response = IOUtils.toString(inputStream);
    return processResponse(urlString, urlBase, response);
} catch (IOException e) {
    throw new Exception("Error querying url: " + urlString, e);
} finally {
    IoUtil.close(inputStream);
    IoUtil.close(outputStreamWriter);
    IoUtil.close(outputStream);
}

7
如果您已经解决了问题,请标记一个答案为已接受 :) - Tobias
10个回答

91

连接超时(假设是本地网络和多台客户机),通常是由以下原因引起的:

a) 路上某种防火墙会简单地吞噬掉数据包,而不告诉发送者类似于"No Route to host"的信息。

b) 由于错误的网络配置或线路过载而导致的数据包丢失。

c) 太多请求导致服务器负载过大。

d) 服务器上同时可用的线程/进程数量较少,导致所有线程/进程都被占用。这种情况尤其发生在需要长时间运行的请求上,并可能与c)结合在一起。


1
帮助我调试此问题的方法是ping我向其发出请求的服务器。我发现URL解析为公共IP,而不是我打算使用的私有IP。在/etc/hosts文件中添加新映射可以解决该问题。我添加这个评论以防其他人遇到类似的问题。 - Bouramas

34
如果在同一台机器上的Web浏览器中该URL可以正常工作,那么可能是Java代码没有使用与浏览器连接到该URL时使用的HTTP代理。

这里是SO链接 - 如何在Java中启用HTTP_PROXY https://dev59.com/vnVD5IYBdhLWcg3wAWkO#120802 - Karan Kaw

8
错误提示已经说明了问题:连接超时。这意味着您的请求没有在一定的时间内得到响应(默认时间)。没有收到响应的原因可能是以下之一:
a)IP/域或端口不正确
b)IP/域或端口(即服务)停止运行
c)IP/域需要更长的时间才能响应您的默认超时时间
d)防火墙正在阻止您使用的任何端口上的请求或响应
e)防火墙正在阻止对特定主机的请求
f)您的互联网访问被关闭
g)您的现场服务器出现故障,例如在“rest-API调用”的情况下。
请注意,ISP可能会设置防火墙和端口或IP阻止。

5
我建议在获取输出流之前提高连接超时时间,方法如下:
urlConnection.setConnectTimeout(1000);

其中1000是毫秒(1000毫秒=1秒)。


26
那不是提高它,而是大幅降低它。默认情况下大约一分钟,你不能增加它,只能降低它。 - user207421

4
  • 尝试使用 Telnet 查看是否存在防火墙问题
  • 执行 tracert/traceroute 查找跃点数

traceroute 去哪里? - aircraft
1
显然,针对你遇到错误的IP地址。 - John Lord

3

我用以下方法解决了我的问题:

System.setProperty("https.proxyHost", "myProxy");
System.setProperty("https.proxyPort", "80");

or http.proxyHost...


3
当URL可用时,为什么会发生“java.net.ConnectException: Connection timed out”异常?
因为URLConnection(HttpURLConnection/HttpsURLConnection)不稳定。您可以在此处此处阅读相关信息。 我们的解决方案有两个步骤:
a)通过setFixedLengthStreamingMode设置ContentLength。
b)如果失败,请捕获任何TimeoutException并重试。

1
这可能是IPv6问题(主机发布了IPv6 AAAA地址,而用户主机认为已配置为IPv6,但实际上连接不正确)。这也可能是网络MTU问题、防火墙阻止,或目标主机可能会发布不同的IP地址(随机或基于原始国家),其中并非所有都可达。或者类似的网络问题。
除了设置超时和添加良好的错误消息(特别是打印出主机的解析地址),您无法做太多事情。如果要使其更加健壮,请添加重试、并行尝试所有地址,并查看Java平台上的名称解析缓存(正面和负面)。

0
这种情况发生的原因是远程服务器只允许特定的IP地址,但不包括它自己的IP地址。我试图从服务器的URL中呈现图像,结果一切都停止了,显示了超时错误。
请确保服务器允许其自己的IP地址,或者您正在从实际存在的远程URL呈现内容。

0

有可能您的IP/主机被远程主机屏蔽,特别是如果它认为您访问过于频繁。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接