سؤال

أستخدم httpurlconnection للقيام بنشر HTTP لكنني لا أعود دائمًا إلى الاستجابة الكاملة. أردت تصحيح المشكلة ، لكن عندما أخطو كل سطر نجح. اعتقدت أنها يجب أن تكون مشكلة توقيت ، لذا أضفت 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()));
        }

يولد رؤوس 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

رأس الاتصال "قريب" ولكن ما زلت لا أستطيع قراءة الاستجابة بأكملها. أي فكرة ماذا أفعل خطأ؟

هل كانت مفيدة؟

المحلول

أعتقد أن مشكلتك في هذا السطر:

while (is.available() > 0) {

حسب جافادوك ، available لا يحظر وينتظر حتى تتوفر جميع البيانات ، لذلك قد تحصل على الحزمة الأولى ثم ستعود خاطئة. الطريقة الصحيحة للقراءة من inputstream هي مثل هذا:

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

ستعود القراءة إلى -1 عندما لا يوجد شيء في الإدخال أو يتم إغلاق الاتصال ، وسوف يمنع الشبكة وانتظر الشبكة أثناء القيام بذلك. القراءة هي أيضا أكثر بكثير من استخدام البايتات.

نصائح أخرى

ربما فاتني ذلك ، ولكن ما نوع البيانات من "الإدخال" في الكود الخاص بك؟ شيء غريب حول inputstreams بشكل عام هو أن أساليب القراءة (...) تميل إلى حظرها حتى تتوفر البيانات ، ثم إرجاع تلك البيانات فقط. ستحتاج فعليًا إلى الاستمرار في القراءة من InputStream وإلحاقها بـ BytearRayInputStream أو بنية أخرى حتى تجبر EofException بشكل صريح.

إذا كنت تقرأ الرسالة بأكملها في وقت ما يمكنك مقارنة ISR.Available () بالمحتوى المتوقع. هكذا فعلت ذلك:

public byte[] readData(HttpURLConnection conn)
        throws IOException, InterruptedException {
    String _connlen = conn.getHeaderField("Content-Length");
    int connlen = Integer.parseInt(_connlen);
    InputStream isr = null;
    byte[] bytes = new byte[connlen];

    try {
        isr = conn.getInputStream();

        //security count that it doesn't begin to hang
        int maxcounter = 0;
        //wait till all data is avalibal, max 5sec
        while((isr.available() != connlen) && (maxcounter  < 5000)){
            Thread.sleep(1);
            maxcounter++;
        }
        //Throw if not all data could be read
        if(maxcounter >= 5000)
            throw new IllegalAccessError(); 

        //read the data         
        if(isr.read(bytes, 0, connlen) < 0)
            throw new IllegalAccessError();     


    } finally {
        if (isr != null)
            isr.close();
    }

    return bytes;
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top