为什么会出现“java.net.ConnectException:连接超时”? URL启动时出现异常?
我的代码中经常出现 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);
}
I'm getting a ConnectException: Connection timed out
with some frequency from my code. The URL I am trying to hit is up. The same code works for some users, but not others. It seems like once one user starts to get this exception they continue to get the exception.
Here is the stack trace:
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)
Here is a snippet from my code:
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);
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
您的 IP/主机有可能被远程主机阻止,尤其是当它认为您的攻击太过分时。
There is a possibility that your IP/host are blocked by the remote host, especially if it thinks you are hitting it too hard.
发生这种情况的原因是,远程服务器只允许特定的 IP 地址,但不允许其自己的 IP 地址,并且我试图从服务器的 URL 渲染图像......所以一切都会停止,显示您的超时错误已经...
确保服务器允许其自己的 IP,或者您正在从实际存在的某个远程 URL 渲染内容。
The reason why this happened to me was that a remote server was allowing only certain IP addressed but not its own, and I was trying to render the images from the server's URLs... so everything would simply halt, displaying the timeout error that you had...
Make sure that either the server is allowing its own IP, or that you are rendering things from some remote URL that actually exists.
错误消息说明了一切:您的连接超时。 这意味着您的请求在某个(默认)时间范围内没有得到响应。 未收到响应的原因可能是以下之一:
a) IP/域或端口不正确
b) IP/域或端口(即服务)已关闭
c) IP/域花费的时间比默认值长响应超时
d) 您的防火墙阻止了您正在使用的任何端口上的请求或响应
e) 您的防火墙阻止了对该特定主机的请求
f) 您的互联网访问已关闭
g) 您的实时服务器已关闭即在“rest-API 调用”的情况下。
请注意,您的 ISP 可能会设置防火墙和端口或 IP 阻止
The error message says it all: your connection timed out. This means your request did not get a response within some (default) timeframe. The reasons that no response was received is likely to be one of:
a) The IP/domain or port is incorrect
b) The IP/domain or port (i.e service) is down
c) The IP/domain is taking longer than your default timeout to respond
d) You have a firewall that is blocking requests or responses on whatever port you are using
e) You have a firewall that is blocking requests to that particular host
f) Your internet access is down
g) Your live-server is down i.e in case of "rest-API call".
Note that firewalls and port or IP blocking may be in place by your ISP
如果 URL 在同一台计算机上的 Web 浏览器中工作正常,则可能是 Java 代码未使用浏览器用于连接到 URL 的 HTTP 代理。
If the URL works fine in the web browser on the same machine, it might be that the Java code isn't using the HTTP proxy the browser is using for connecting to the URL.
连接超时(假设有本地网络和多台客户端计算机)通常是由于
a) 某种防火墙简单地吃掉数据包而不告诉发送者“没有到主机的路由”之类的信息
b) 由于错误的网络配置而导致数据包丢失或线路过载
c) 太多请求使服务器过载
d) 服务器上同时可用的线程/进程数量较少,导致所有线程/进程都被占用。 这种情况尤其发生在需要很长时间运行并且可能与 c) 结合的请求时。
Connection timeouts (assuming a local network and several client machines) typically result from
a) some kind of firewall on the way that simply eats the packets without telling the sender things like "No Route to host"
b) packet loss due to wrong network configuration or line overload
c) too many requests overloading the server
d) a small number of simultaneously available threads/processes on the server which leads to all of them being taken. This happens especially with requests that take a long time to run and may combine with c).
我建议在获取输出流之前提高连接超时时间,如下所示:
其中 1000 以毫秒为单位(1000 毫秒 = 1 秒)。
I'd recommend raising the connection timeout time before getting the output stream, like so:
Where 1000 is in milliseconds (1000 milliseconds = 1 second).
tracert
/traceroute
来查找跳数tracert
/traceroute
to find number of hops我用以下方法解决了我的问题:
或
http.proxyHost
...I solved my problem with:
or
http.proxyHost
...因为URLConnection(HttpURLConnection/HttpsURLConnection)不稳定。 您可以在此处和此处。
我们的解决方案有两件事:
a) 通过 setFixedLengthStreamingMode 设置 ContentLength
b) 捕获任何 TimeoutException,如果失败则重试。
Because the URLConnection (HttpURLConnection/HttpsURLConnection) is erratic. You can read about this here and here.
Our solution were two things:
a) set the ContentLength via
setFixedLengthStreamingMode
b) catch any TimeoutException and retry if it failed.
这可能是 IPv6 问题(主机发布 IPv6 AAAA 地址,用户主机认为它已配置为 IPv6,但实际上未正确连接)。 这也可能是网络 MTU 问题、防火墙阻止或目标主机可能发布不同的 IP 地址(随机或基于发起者国家/地区),而这些地址并非全部可达。 或者类似的网络问题。
除了设置超时和添加良好的错误消息(特别是打印出主机的解析地址)之外,您不能做太多事情。 如果您想让它更加健壮,请添加重试、并行尝试所有地址,并研究 Java 平台上的名称解析缓存(正向和负向)。
This can be a IPv6 problem (the host publishes an IPv6 AAAA-Address and the users host thinks it is configured for IPv6 but it is actually not correctly connected). This can also be a network MTU problem, a firewall block, or the target host might publish different IP addresses (randomly or based on originators country) which are not all reachable. Or similliar network problems.
You cant do much besides setting a timeout and adding good error messages (especially printing out the hosts' resolved address). If you want to make it more robust add retry, parallel trying of all addresses and also look into name resolution caching (positive and negative) on the Java platform.