Использование URLConnection - получение тайм-аута соединения во время чтения - как это возможно? - PullRequest
0 голосов
/ 10 января 2020

Мой код имеет следующее:

HttpURLConnection urlConn = (HttpURLConnection) urls[urlIndex].openConnection();
urlConn.setDoInput (true);
urlConn.setDoOutput (true);
urlConn.setUseCaches (false);
urlConn.setRequestProperty("Content-Type", "text/xml;charset="+charset);
urlConn.setConnectTimeout(1000); //1 second
urlConn.setReadTimeout(10000);   // 10 seconds
urlConn.connect();

В последней строке я ожидаю

java.net.SocketTimeoutException: connect timed out

Если не удается установить соединение с сервером. Это было проверено и подтверждено

Я продолжаю отправлять запрос POST:

OutputStreamWriter printout = new OutputStreamWriter(urlConn.getOutputStream (), charset);
printout.write(myRequest);
printout.flush();
printout.close();

Затем я читаю ответ

myRespones = UtilityClass.readFromInputStream(urlConn.getInputStream(), charset);
urlConn.getInputStream().close();

При вызове метода urlConn.getInputStream () Я ожидаю тайм-аут чтения, если сервер не отвечает в течение 10 секунд. Это было проверено и подтверждено.

То, что мы делаем в уникальном случае, - это следующая трассировка стека из getInputStream метод

Caused by: java.net.SocketTimeoutException: connect timed out
at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method)
at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:96)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:380)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:236)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:218)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:183)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:403)
at java.net.Socket.connect(Socket.java:666)
at sun.net.NetworkClient.doConnect(NetworkClient.java:187)
at sun.net.www.http.HttpClient.openServer(HttpClient.java:494)
at sun.net.www.http.HttpClient.openServer(HttpClient.java:589)
at sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:871)
at sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:709)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1602)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1507)

Как это вообще возможно получите время соединения, как только соединение будет установлено . Я ожидаю только время чтения. Это также подтверждается javado c для метода getInputStream

Возвращает входной поток, который читает из этого открытого соединения. Исключение SocketTimeoutException может генерироваться при чтении из возвращенного входного потока, если время ожидания чтения истекает до того, как данные станут доступны для чтения.


Обновление

Сделано еще немного тестирования, создав свой собственный клиент и сервер. Я не изменял retryPost:

  1. Соединение успешно с клиента-> сервер выключения-> getInputStream ()
  2. Соединение успешно с клиента-> getInputStream () -> Завершение работы сервера во время обработки request

В обоих случаях я получаю одинаковую трассировку стека (ниже). Похоже, что логи запроса на подключение и отправку c являются частью собственного кода " waitForConnect "

Переменная bytesTransferred для исключения равна 0 в обоих случаях.

Это говорит мне о том, что в Java было бы невозможно различить guish между ошибкой подключения, когда запрос не отправлен и где запрос отправлен, таким образом, также было бы невозможно узнать, когда может быть выполнено переключение при сбое. и запрос повторен против другого сервера.

Caused by: java.net.SocketTimeoutException: connect timed out
    at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method)
    at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:96)
    at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:380)
    at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:236)
    at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:218)
    at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:183)
    at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:403)
    at java.net.Socket.connect(Socket.java:666)
    at sun.net.NetworkClient.doConnect(NetworkClient.java:187)
    at sun.net.www.http.HttpClient.openServer(HttpClient.java:494)
    at sun.net.www.http.HttpClient.openServer(HttpClient.java:589)
    at sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:871)
    at sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:709)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1602)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1507)

Если я установлю значение retryPost в false, я получу другое сообщение об ошибке, но все равно идентичную трассировку стека, независимо от того, был ли запрос отправлен или нет.

Caused by: java.net.SocketException: Unexpected end of file from server
    at sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:882)
    at sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:709)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1602)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1507)

Мне кажется, это невозможно сделать в Java.

...