HttpURLConnection не читает целый ответ

Я использую HttpURLConnection, чтобы сделать HTTP POST, но я не всегда возвращаю полный ответ. Я хотел отладить проблему, но когда я ступаю через каждую строку, она работала. Я думал, что это должна быть проблема синхронизации, таким образом, я добавил Thread.sleep, и это действительно заставило мой код работать, но это - только временное обходное решение. Интересно, почему это происходит и как решить. Вот мой код:

public static InputStream doPOST(String input, String inputMimeType, String url, Map<String, String> httpHeaders, String expectedMimeType) throws MalformedURLException, IOException {

    URL u = new URL(url);
    URLConnection c = u.openConnection();
    InputStream in = null;
    String mediaType = null;
    if (c instanceof HttpURLConnection) {

        //c.setConnectTimeout(1000000);
        //c.setReadTimeout(1000000);

        HttpURLConnection h = (HttpURLConnection)c;
        h.setRequestMethod("POST");
        //h.setChunkedStreamingMode(-1);
        setAccept(h, expectedMimeType);
        h.setRequestProperty("Content-Type", inputMimeType);

        for(String key: httpHeaders.keySet()) {
            h.setRequestProperty(key, httpHeaders.get(key));

            if (logger.isDebugEnabled()) {
                logger.debug("Request property key : " + key + " / value : " + httpHeaders.get(key));
            }

        }

        h.setDoOutput(true);
        h.connect();

        OutputStream out = h.getOutputStream();

        out.write(input.getBytes());

        out.close();

        mediaType = h.getContentType();

        logger.debug(" ------------------ sleep ------------------ START");
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        logger.debug(" ------------------ sleep ------------------ END");

        if (h.getResponseCode() < 400) {
            in = h.getInputStream();
        } else {
            in = h.getErrorStream();
        }
    }
    return in;

}

позже я делаю следующее для чтения входного потока

        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        while (is.available() > 0) {
            bos.write(is.read());
        }
        is.close();

        //is.read(bytes);
        if (logger.isDebugEnabled()) {
            logger.debug(" Response lenght is : " + is.available());
            //logger.debug("RAW response is " + new String(bytes));
            logger.debug("RAW response is " + new String(bos.toByteArray()));
        }

Это genearates следующие HTTP-заголовки

POST /emailauthentication/ HTTP/1.1
Accept: application/xml
Content-Type: application/xml
Authorization: OAuth oauth_consumer_key="b465472b-d872-42b9-030e-4e74b9b60e39",oauth_nonce="YnDb5eepuLm%2Fbs",oauth_signature="dbN%2FWeWs2G00mk%2BX6uIi3thJxlM%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1276524919", oauth_token="", oauth_version="1.0"
User-Agent: Java/1.6.0_20
Host: test:6580
Connection: keep-alive
Content-Length: 1107

В других сообщениях было предложено выключить активный при помощи

http.keepAlive=false

системное свойство, я попробовал это и заголовки, измененные на

POST /emailauthentication/ HTTP/1.1
Accept: application/xml
Content-Type: application/xml
Authorization: OAuth oauth_consumer_key="b465472b-d872-42b9-030e-4e74b9b60e39", oauth_nonce="Eaiezrj6X4Ttt0", oauth_signature="ND9fAdZMqbYPR2j%2FXUCZmI90rSI%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1276526608", oauth_token="", oauth_version="1.0"
User-Agent: Java/1.6.0_20
Host: test:6580
Connection: close
Content-Length: 1107

заголовок Соединения "близок", но я все еще не могу считать целый ответ. Какая-либо идея, что я делаю неправильно?

7
задан Termininja 24 January 2016 в 10:35
поделиться

2 ответа

Я думаю, ваша проблема в этой строке:

while (is.available() > 0) {

Согласно javadoc, available не блокирует и не ждет, пока все данные станут доступны, поэтому вы можете получить первый пакет, а затем он вернет false. Правильный способ чтения из InputStream выглядит следующим образом:

int len;
byte[] buffer = new byte[4096];
while (-1 != (len = in.read(buffer))) {
  bos.write(buffer, 0, len);
}

Read вернет -1, когда во входном потоке ничего не останется или соединение закрыто, и при этом он заблокируется и будет ждать сеть. Чтение массивов также намного производительнее, чем использование одиночных байтов.

14
ответ дан 6 December 2019 в 15:18
поделиться

Может быть, я это пропустил, но какой тип данных "ввод" в вашем коде? Что-то странное в InputStreams в целом заключается в том, что методы read (...) имеют тенденцию блокироваться до тех пор, пока данные не станут доступны, а затем возвращают только эти данные. На самом деле вам нужно будет продолжать читать из вашего InputStream и добавлять к ByteArrayInputStream или какой-либо другой структуре, пока вы явно не вызовете EOFException.

0
ответ дан 6 December 2019 в 15:18
поделиться
Другие вопросы по тегам:

Похожие вопросы: