HTTP-запрос Java иногда зависает - PullRequest
3 голосов
/ 29 апреля 2010

В большинстве случаев мои HTTP-запросы работают без проблем. Однако иногда они будут висеть.

Код, который я использую, настроен таким образом, чтобы в случае успешного выполнения запроса (с кодом ответа 200 или 201) вызывался метод screen.requestSucceeded (). Если запрос не выполняется, вызовите screen.requestFailed ().

Однако, когда запрос зависает, он делает это до вызова одного из вышеуказанных методов. Что-то не так с моим кодом? Должен ли я использовать какую-то лучшую практику для предотвращения зависания?

Ниже приведен мой код. Буду признателен за любую помощь. Спасибо!

HttpConnection connection = (HttpConnection) Connector.open(url
                    + connectionParameters);

            connection.setRequestMethod(method);
            connection.setRequestProperty("WWW-Authenticate",
                    "OAuth realm=api.netflix.com");
            if (method.equals("POST") && postData != null) {
            connection.setRequestProperty("Content-Type",
                    "application/x-www-form-urlencoded");
            connection.setRequestProperty("Content-Length", Integer
                    .toString(postData.length));
            OutputStream requestOutput = connection.openOutputStream();
            requestOutput.write(postData);
            requestOutput.close();
        }
            int responseCode = connection.getResponseCode();
            System.out.println("RESPONSE CODE: " + responseCode);
            if (connection instanceof HttpsConnection) {
                HttpsConnection secureConnection = (HttpsConnection) connection;
                String issuer = secureConnection.getSecurityInfo()
                        .getServerCertificate().getIssuer();
                UiApplication.getUiApplication().invokeLater(
                        new DialogRunner(
                                "Secure Connection! Certificate issued by: "
                                        + issuer));

            }

            if (responseCode != 200 && responseCode != 201) {
                screen.requestFailed("Unexpected response code: "
                        + responseCode);
                connection.close();
                return;
            }

            String contentType = connection.getHeaderField("Content-type");
            ByteArrayOutputStream baos = new ByteArrayOutputStream();

            InputStream responseData = connection.openInputStream();
            byte[] buffer = new byte[20000];
            int bytesRead = 0;
            while ((bytesRead = responseData.read(buffer)) > 0) {
                baos.write(buffer, 0, bytesRead);
            }
            baos.close();
            connection.close();
            screen.requestSucceeded(baos.toByteArray(), contentType);
        } catch (IOException ex) {
            screen.requestFailed(ex.toString());
        }

Ответы [ 4 ]

6 голосов
/ 29 апреля 2010

Без следа, я просто стреляю в темноте.

Попробуйте добавить это 2 звонка,

System.setProperty("http.keepAlive", "false");

connection.setRequestProperty("Connection", "close");

Поддержание активности является распространенной причиной устаревших соединений. Эти вызовы отключат его.

2 голосов
/ 29 апреля 2010

Я не вижу проблем с кодом. Это может быть связано с тем, что на вашей платформе периодически возникает ошибка или что веб-сайт вызывает зависание соединения. Может помочь изменение параметров подключения, таких как сохранение активности.

Но даже при установленном тайм-ауте сокеты могут зависать бесконечно - один из друзей удачно продемонстрировал мне это несколько лет назад, вытащив сетевой кабель - моя программа просто зависла там навсегда, даже если для SO_TIMEOUT установлено значение 30 секунд.

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

1 голос
/ 02 ноября 2010

Я тоже заметил эту проблему на Blackberry OS 5.0. Нет способа воспроизвести это надежно. В итоге мы использовали дополнительный поток, используя wait / notify вместе с Timertask.

1 голос
/ 29 апреля 2010

Я вижу, у вас есть код для обработки отправки запроса типа "POST", однако нет ничего, что записывает данные POST в запросе. Если тип соединения «POST», то ДОЛЖНО выполнить connection.getResponseCode ():

  • установить заголовок "Content-Length"
  • установить заголовок «Content-Type» (что вы делаете)
  • получить OutputStream из соединения, используя connection.openOutputStream ()
  • записать данные POST (формы) в OutputStream
  • закрыть OutputStream
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...