Почему возникает исключение «java.net.ConnectException: время ожидания соединения истекло», когда URL открыт?

86

Я получаю сообщение 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
Пожалуйста, отметьте один ответ как одобренный, если вы решили свою проблему :)
Тобиас

Ответы:

84

Тайм-ауты подключения (при условии наличия локальной сети и нескольких клиентских машин) обычно возникают из-за

а) какой-то брандмауэр на пути, который просто съедает пакеты, не сообщая отправителю такие вещи, как "Нет маршрута к хосту"

б) потеря пакетов из-за неправильной конфигурации сети или перегрузки линии

в) слишком много запросов, перегружающих сервер

г) небольшое количество одновременно доступных потоков / процессов на сервере, что приводит к тому, что все они заняты. Это происходит особенно с запросами, выполнение которых занимает много времени и может сочетаться с c).

Надеюсь это поможет.

Jumpy
источник
Что помогло мне отладить эту проблему, так это проверка связи с сервером, к которому я делал запрос. Я обнаружил, что URL-адрес разрешен для общедоступного IP-адреса, а не для частного IP, который я намеревался. Новое сопоставление в файле / etc / hosts позволило решить проблему. Я добавляю комментарий на случай, если кто-то еще столкнется с подобной проблемой.
Bouramas 03
31

Если URL-адрес нормально работает в веб-браузере на том же компьютере, возможно, код Java не использует прокси-сервер HTTP, который браузер использует для подключения к URL-адресу.

Александр
источник
6

Сообщение об ошибке говорит само за себя: время ожидания соединения истекло. Это означает, что ваш запрос не получил ответа в течение некоторого (по умолчанию) периода времени. Причины, по которым не был получен ответ, могут быть одной из следующих:

а) IP / домен или порт неверны

б) IP / домен или порт (т. е. служба) не работают

c) IP / домен требует больше времени, чем время ожидания по умолчанию для ответа

г) У вас есть брандмауэр, который блокирует запросы или ответы на любом используемом вами порту.

д) У вас есть брандмауэр, который блокирует запросы к этому конкретному хосту.

е) Ваш доступ в Интернет отключен

ж) Ваш live-сервер не работает, т.е. в случае "вызова rest-API".

Обратите внимание, что ваш интернет-провайдер может установить брандмауэры и блокировку портов или IP-адресов.

М. Хамза Джавед
источник
4

Я бы рекомендовал увеличить время ожидания соединения перед получением выходного потока, например:

urlConnection.setConnectTimeout(1000);

Где 1000 - в миллисекундах (1000 миллисекунд = 1 секунда).

Пауэрлорд
источник
21
Это не повышение, а резкое понижение. По умолчанию это около минуты, и вы не можете его увеличить, вы можете только уменьшить его.
Marquis of Lorne
3
  • попробуйте выполнить Telnet, чтобы увидеть какие-либо проблемы с брандмауэром
  • выполнить tracert/ tracerouteнайти количество прыжков
голубоватый
источник
traceroute куда?
Самолет
очевидно, к любому IP-адресу, с которым вы получали ошибку.
Джон Лорд
2

Я решил свою проблему:

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

или http.proxyHost...

Никник
источник
1

Это может быть проблема IPv6 (хост публикует AAAA-адрес IPv6, а пользовательский хост думает, что он настроен для IPv6, но на самом деле он неправильно подключен). Это также может быть проблема с сетевым MTU, блокировка брандмауэра или целевой хост может публиковать разные IP-адреса (случайным образом или в зависимости от страны отправителя), которые не все достижимы. Или похожие проблемы с сетью.

Вы ничего не можете сделать, кроме установки тайм-аута и добавления хороших сообщений об ошибках (особенно распечатки разрешенного адреса хоста). Если вы хотите сделать его более надежным, добавьте повторную попытку, параллельную попытку всех адресов, а также изучите кеширование разрешения имен (положительное и отрицательное) на платформе Java.

Eckes
источник
1

Почему возникает исключение «java.net.ConnectException: время ожидания соединения истекло», когда URL открыт?

Поскольку URLConnection (HttpURLConnection / HttpsURLConnection) ошибочен. Вы можете прочитать об этом здесь и здесь . Нашим решением были две вещи:

а) установите ContentLength через setFixedLengthStreamingMode

б) поймать любое исключение TimeoutException и повторить попытку, если это не удалось.

Lonzak
источник
0

Существует вероятность того, что ваш IP / хост заблокирован удаленным хостом, особенно если он думает, что вы слишком сильно бьете по нему.

ларсиви
источник
0

Причина, по которой это произошло со мной, заключалась в том, что удаленный сервер разрешал только определенный IP-адрес, но не свой собственный, и я пытался визуализировать изображения из URL-адресов сервера ... так что все просто останавливалось, отображая ошибку тайм-аута, которую вы было...

Убедитесь, что либо сервер разрешает свой собственный IP-адрес, либо вы визуализируете данные с некоторого удаленного URL-адреса, который действительно существует.

Дамир Олежар
источник