سؤال

لدي مشكلة مع Jakarta Commons HttpClient. قبل أن يحصل HTTPServer المكتوبة على طلب حقيقي، هناك طلب واحد فارغ تماما. هذه هي المشكلة الأولى. تم حل المشكلة الأولى. كان سبب وجود UrlConnection غير الضروري! المشكلة الثانية هي، وأحيانا تنتهي بيانات الطلب بعد الخط الثالث أو الرابع لطلب HTTP:

POST / HTTP/1.1
User-Agent: Jakarta Commons-HttpClient/3.1
Host: 127.0.0.1:4232

لتصحيح الأخطاء وأنا أستخدم محور TcpMonitor. هناك كل الأشياء على ما يرام ولكن الطلب الفارغ.

كيف أعالج الدفق:

StringBuffer requestBuffer = new StringBuffer();

InputStreamReader is = new InputStreamReader(socket.getInputStream(), "UTF-8");

int byteIn = -1;
do {
    byteIn = is.read();
    if (byteIn > 0) {
        requestBuffer.append((char) byteIn);
    }
} while (byteIn != -1 && is.ready());

String requestData = requestBuffer.toString();

وجدت طريقة جديدة لمعالجة الدفق. قرأت جميع معلمات الرأس واستخدام "طول المحتوى" لقراءة بيانات النشر.

InputStream is = mySocket.getInputStream();
if (is == null) {
    return;
}
BufferedReader in = new BufferedReader(new InputStreamReader(is, "UTF-8"));

// Read the request line
// ...
// ...

// Parse the header
Properties header = new Properties();
if (st.hasMoreTokens()) {
    String line = in.readLine();
    while (line != null && line.trim().length() > 0) {
        int p = line.indexOf(':');
        header.put(line.substring(0, p).trim().toLowerCase(), line.substring(p + 1).trim());
        line = in.readLine();
    }
}

// If the method is POST, there may be parameters
// in data section, too, read it:
String postLine = "";
if (method.equalsIgnoreCase("POST")) {
    long size = 0x7FFFFFFFFFFFFFFFl;
    String contentLength = header.getProperty("content-length");
    if (contentLength != null) {
        try {
            size = Integer.parseInt(contentLength);
        } catch (NumberFormatException ex) {
        }
    }
    postLine = "";
    char buf[] = new char[512];
    int read = in.read(buf);
    while (read >= 0 && size > 0 && !postLine.endsWith("\r\n")) {
        size -= read;
        postLine += String.valueOf(buf, 0, read);
        if (size > 0) {
            read = in.read(buf);
        }
    }
    postLine = postLine.trim();
    decodeParms(postLine, parms);
}

كيف أرسل الطلب:

client.getParams().setSoTimeout(30000);

method = new PostMethod(url.getPath());
method.getParams().setContentCharset("utf-8");
method.setRequestHeader("Content-Type", "application/xml; charset=utf-8");
method.addRequestHeader("Connection", "close");
method.setFollowRedirects(false);

byte[] requestXml = getRequestXml();

method.setRequestEntity(new InputStreamRequestEntity(new ByteArrayInputStream(requestXml)));

client.executeMethod(method);

int statusCode = method.getStatusCode();

هل لديك أي شخص منكم فكرة عن كيفية حل هذه المشكلات المشكلة؟

اليكيال

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

المحلول

قد يكون الأمر يتعلق بالشرط الثاني في حلقة أثناء الحلقة، قد تعود الطريقة ISReady () خطأ عند حظر القراءة التالية - لكنك لا تهتم حقا إذا كنعت أم لا، حتى نتمكن من إزالتها (أنت يمكن قراءة المزيد هنا: http://java.sun.com/j2se/1.5.0/docs/api/java/io/ibutstreamreader.html#ready٪28٪29. ). حاول تغيير هذا:

byte[] buf = new byte[500];
while((is.read(buf))>-1){
  requestBuffer.append(new String(buf).trim());
  buf = new byte[500];
}

الآن يجب أن تحصل على الطلب بأكمله.

نصائح أخرى

لا أعرف عن المشكلة الأولى، لكنني أعتقد أن مشكلتك الثانية ترجع إلى ذلك:

} while (byteIn != -1 && is.ready());

إذا كان المرسل ليس سريعا بدرجة كافية من إرسال البيانات، فقد يستدعي جهاز الاستقبال is.ready() قبل إرسال الحزمة التالية. هذا سوف يسبب ذلك is.ready() لكي ترجع false مما سيؤدي إلى توقف الحلقة.

الحد الأدنى من الإصلاح هو تغيير هذا السطر إلى:

} while (byteIn != -1);

تعديل

ولكن حقا، تحتاج إلى إعادة كتابة الطريقة على طول خطوط @ إجابة simonlord. إنها فكرة سيئة حقا لقراءة دفق غير مقيد بايت واحد في وقت واحد. ينتهي بك الأمر في إجراء مكالمة للنظام لكل منهما read اتصل، وهو غير فعال بشكل فظيع.

تحرير 2.

السبب الذي يزيل is.ready() التأخيرات التي تسبب لأنك لم تكن إيلاء اهتمام مناسب بروتوكول HTTP. كانت المشكلة هي رمز httpClient هو الحفاظ على جانب الطلب من اتصال TCP مفتوح للسماح بإعادة استخدام الاتصال. كان الحل البسيط (ولكن دون المستوى الأمثل) هو لتكوين HTTPClient لإغلاق جانب الطلب من الاتصال. شهد الكود الخاص بك بعد ذلك مباشرة. ما فعلت فعلا كان حل آخر.

بصراحة يجب أن لا تكون كذلك محاولة لتنفيذ بروتوكول HTTP Sidel-side إلا إذا كنت مستعدا لفهم مواصفات HTTP بأكملها في العمق وتنفيذها بأمانة. من الفرص أن التنفيذ الحالي سيكون أسرع وأكثر موثوقية من أي شيء يمكنك طرحه معا. المشكلة مع تنفيذ مجموعة فرعية من المواصفات هي أن الخادم الخاص بك قد يحتاج إلى التحدث إلى متصفح حقيقي يستخدم أجزاء من المواصفات التي لم تزعجك للتنفيذ / الاختبار.

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