Таймаут Java HTTPUrlConnection не работает
Я написал программу, которая открывает httpurlconnection к веб-сайту через случайные прокси. Мое httpurlconnection называется conn. Теперь я знаю, что некоторые из этих прокси могут быть слишком медленными, поэтому я установил тайм-аут соединения на 40000 миллисекунд с conn.setConnectTimeout(40000)
а также conn.setReadTimeout(40000)
,
После этого я получил этот код:
long diff = 0;
long starttime = 0;
long endtime = 0;
try
{
starttime = System.currentTimeMillis();
conn.connect();
endtime = System.currentTimeMillis();
diff = endtime - starttime;
if (endtime <= starttime + conn.getConnectTimeout())
{
//Trying to read sourecode
InputStreamReader isrConn = new InputStreamReader(conn.getInputStream());
BufferedReader brConn = new BufferedReader(isrConn);
line = brConn.readLine();
while (line != null)
{
response += line + "\t";
try
{
line = brConn.readLine();
} catch (IOException e)
{
printError("Reading sourcecode failed.");
}
}
}
else
{
response = "blabla.";
}
// If conn.connect failed
} catch (IOException e)
{
endtime = System.currentTimeMillis();
diff = endtime - starttime;
response = "Message: "+e.getMessage() +" MyTimeout:"+ conn.getConnectTimeout() +" Actual time passed: "+ diff;
e.printStackTrace();
}
Есть причины, по которым соединение может прерваться, поэтому во многих случаях я получаю последний блок catch и получаю следующий вывод:
Сообщение: истекло время соединения: подключено MyTimeout:40000 фактическое время прошло: 21012
Сообщение: истекло время соединения: подключено MyTimeout:40000 фактическое время прошло: 21016
Сообщение: истекло время соединения: подключено MyTimeout:40000 фактическое время прошло: 21010
Сообщение: истекло время соединения: подключено MyTimeout:40000 Фактическое время прошло: 21009
Поэтому мой вопрос будет таким: я установил тайм-аут на 40000 миллисекунд, но через примерно 21000 миллисекунд я получаю ответ "Время ожидания истекло", кто-нибудь из вас знает, почему это так?
РЕДАКТИРОВАТЬ: я использую Windows 7, и теперь я добавил e.printStackTrace() в блок catch, как сказано в комментариях. пока спасибо. вывод теперь (пример):
java.net.ConnectException: Connection timed out: connect
at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method)
at java.net.DualStackPlainSocketImpl.socketConnect(Unknown Source)
at java.net.AbstractPlainSocketImpl.doConnect(Unknown Source)
at java.net.AbstractPlainSocketImpl.connectToAddress(Unknown Source)
at java.net.AbstractPlainSocketImpl.connect(Unknown Source)
at java.net.PlainSocketImpl.connect(Unknown Source)
at java.net.Socket.connect(Unknown Source)
at sun.net.NetworkClient.doConnect(Unknown Source)
at sun.net.www.http.HttpClient.openServer(Unknown Source)
at sun.net.www.http.HttpClient$1.run(Unknown Source)
at sun.net.www.http.HttpClient$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at sun.net.www.http.HttpClient.privilegedOpenServer(Unknown Source)
at sun.net.www.http.HttpClient.openServer(Unknown Source)
at sun.net.www.http.HttpClient.<init>(Unknown Source)
at sun.net.www.http.HttpClient.New(Unknown Source)
at sun.net.www.http.HttpClient.New(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.plainConnect(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.connect(Unknown Source)
at TestThread.getSourcePage(TestThread.java:361)
at TestThread.aChecker(TestThread.java:216)
at TestThread.getNextProxy(TestThread.java:169)
at TestThread.getNextC(TestThread.java:157)
at TestThread.aChecker(TestThread.java:273)
at TestThread.getNextProxy(TestThread.java:169)
at TestThread.aChecker(TestThread.java:295)
at TestThread.getNextProxy(TestThread.java:169)
at TestThread.getNextC(TestThread.java:157)
at TestThread.run(TestThread.java:103)
at java.lang.Thread.run(Unknown Source)
Message: Connection timed out: connect MyTimeout:40000 Actual time passed: 21015
2 ответа
Посмотрите на исключение, которое вы получили:
Самая большая подсказка: вы получаете java.net.ConnectException
Согласно Javadoc, java.net.ConnectException
означает, что соединение было отклонено удаленно по причинам, таким как процесс не прослушивает порт.
public class ConnectException
extends SocketException
Signals that an error occurred while attempting to connect a socket to a remote address and port.
Typically, the connection was refused remotely (e.g., no process is listening on the remote
address/port)
Что вы настроили в HttpUrlConnection:
Тайм-аут для соединения (учитывая, что удаленный порт принимает соединение). Если время ожидания соединения истекает, вы получаете java.net.SocketTimeoutException
и не java.net.ConnectException
,
Итак, что вызывает java.net.ConnectException
?
Я пробовал следующие тестовые случаи:
+------------+------------+----------------+------------------+---------------------------------+
| Valid Host | Valid Port | Valid Proxy IP | Valid Proxy Port | Exception |
+------------+------------+----------------+------------------+---------------------------------+
#1 | yes | yes | -NA- | -NA- | -- none -- |
#2 | yes | no | -NA- | -NA- | java.net.ConnectException |
+------------+------------+----------------+------------------+---------------------------------+
#3 | yes | yes | yes | yes | -- none -- |
#4 | yes | no | yes | yes | java.net.SocketTimeoutException |
#5 | yes | yes | yes | no | java.net.ConnectException |
+------------+------------+----------------+------------------+---------------------------------+
- Варианты №1, №3 - это счастливые пути, в которых все конфиги верны
- В случае № 4 мы получаем
java.net.SocketTimeoutException
потому что процесс Java может установить соединение (с прокси-портом), но не получает данных для чтения, так как номер порта целевого хоста является недопустимым - В случае № 2, № 5 мы получаем
java.net.ConnectException
потому что порт, на котором процесс Java пытается записи / чтения является недействительным - Значение тайм-аута соединения не подходит для случаев, когда ни один процесс не прослушивает порт, к которому Java-процесс пытается подключиться. Вот почему вы получаете ConnectException до истечения времени ожидания
Message: Connection refused: connect MyTimeout:10000 Actual time passed: 6549
java.net.ConnectException: Connection refused: connect
at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method)
at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:85)
....
....
Заключение:
- Некоторые прокси, к которым вы пытались подключиться, должны быть отключены. Отсюда ява процесс скинул
java.net.ConnectException
- Лучше поймать
java.net.ConnectException
и пометить прокси как недействительный
По моему опыту, HttpUrlConnection не будет время ожидания во время разрешения имени. Если ваше устройство кэшировало целевой адрес, то время ожидания истекло.
Для целей тестирования используйте свой IP-адрес в своем коде.
Это обычно происходит со мной на мобильных устройствах.