سؤال

لقد قرأت أن httpurlConnection يدعم الاتصالات المستمرة ، بحيث يمكن إعادة استخدام الاتصال لطلبات متعددة. لقد جربتها ، وكانت الطريقة الوحيدة لإرسال منشور آخر هي الاتصال بـ OpenConnection للمرة الثانية. وإلا فقد حصلت على مفتاح غير قانوني ("متصل بالفعل") ؛ لقد استخدمت ما يلي:

try{
URL url = new URL("http://someconection.com");
}
catch(Exception e){}
HttpURLConnection con = (HttpURLConnection) url.openConnection();
//set output, input etc
//send POST
//Receive response
//Read whole response
//close input stream
con.disconnect();//have also tested commenting this out
con = (HttpURLConnection) url.openConnection();
//Send new POST

يتم إرسال الطلب الثاني على نفس اتصال TCP (تم التحقق منه باستخدام Wireshark) ولكن لا يمكنني أن أفهم السبب (على الرغم من أن هذا ما أريده) منذ أن وصفت Disconnect. لقد راجعت الكود المصدري لـ HTTPURLConnection والتنفيذ يحافظ على ذاكرة التخزين المؤقت للاتصالات لنفس الوجهات. مشكلتي هي أنني لا أستطيع أن أرى كيف يتم وضع الاتصال مرة أخرى في ذاكرة التخزين المؤقت بعد إرسال الطلب الأول. يغلق الفصل الاتصال وبدون قطع الاتصال ، ما زلت لا أستطيع أن أرى كيف يتم وضع الاتصال مرة أخرى في ذاكرة التخزين المؤقت. لقد رأيت أن ذاكرة التخزين المؤقت لها طريقة تشغيل للذهاب عبر جميع الاتصالات الخاملة (لست متأكدًا من كيفية استدعاءها) ، لكن لا يمكنني العثور على كيفية وضع الاتصال مرة أخرى في ذاكرة التخزين المؤقت. المكان الوحيد الذي يبدو أنه يحدث في الطريقة النهائية لـ HTTPClient ، لكن هذا لا يدعو إلى منشور مع استجابة. هل يمكن لأي شخص مساعدتي في هذا؟

تعديلاهتمامي هو ، ما هو التعامل المناسب لكائن httpurlConnection لإعادة استخدام اتصال TCP. يجب إغلاق دفق الإدخال/الإخراج يليه url.openconnection () ؛ في كل مرة لإرسال الطلب الجديد (تجنب قطع الاتصال ())؟ إذا كانت الإجابة بنعم ، لا يمكنني أن أرى كيف يتم إعادة استخدام الاتصال عندما أتصل بـ url.openconnection () للمرة الثانية ، حيث تمت إزالة الاتصال من ذاكرة التخزين المؤقت للطلب الأول ولم أتمكن من العثور على كيفية إرجاعه. هل من الممكن عدم إعادة الاتصال مرة أخرى إلى ذاكرة التخزين المؤقت (BUG؟) ، لكن نظام التشغيل لم يصدر اتصال TCP حتى الآن وعلى اتصال جديد ، يقوم نظام التشغيل بإرجاع الاتصال المخزن المؤقت (لم يتم إصداره بعد) أو شيء مشابه؟EDIT2كان الوحيدة ذات الصلة التي وجدتها من JDK_Keepalive

... عندما يتصل التطبيق بإغلاق () على inputstream الذي تم إرجاعه بواسطة urlConnection.getInputStream () ، سيحاول معالج بروتوكول HTTP الخاص بـ JDK تنظيف الاتصال وإذا نجح ، ضع الاتصال في ذاكرة التخزين المؤقت للاتصال لإعادة الاستخدام عن طريق طلبات HTTP المستقبلية .

لكنني لست متأكدًا من المعالج هذا. sun.net.www.protocol.http.handler لا يفعل أي تخزين مؤقت كما رأيت شكرا!

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

المحلول

يجب إغلاق دفق الإدخال/الإخراج يليه url.openconnection () ؛ في كل مرة لإرسال الطلب الجديد (تجنب قطع الاتصال ())؟

نعم.

إذا كانت الإجابة بنعم ، لا يمكنني أن أرى كيف يتم إعادة استخدام الاتصال عندما أتصل بـ url.openconnection () للمرة الثانية ، حيث تمت إزالة الاتصال من ذاكرة التخزين المؤقت للطلب الأول ولم أتمكن من العثور على كيفية إرجاعه.

أنت تربك HttpURLConnection مع الكامنة Socket و انها اتصال TCP الأساسي. إنهم ليسوا متماثلين. ال HttpURLConnection الحالات هي GC'D ، والكامنة Socket تم تجميعه ، ما لم تتصل disconnect().

نصائح أخرى

من javadoc for httpurlconnection (تركيزي):

يتم استخدام كل مثيل httpurlconnection لجعل ملف طلب واحد ولكن اتصال الشبكة الأساسية بخادم HTTP قد تتم مشاركته بشفافية بواسطة مثيلات أخرى. استدعاء طرق Close () على inputStream أو OutputStream من httpurlconnection بعد الطلب قد يجوز لطلاب تحرير موارد الشبكة المرتبطة بهذه المثيل ولكن ليس له أي تأثير على أي اتصال مستمر مشترك. استدعاء طريقة disconnect () مايو أغلق المقبس الأساسي إذا كان الاتصال المستمر في وضع الخمول في ذلك الوقت.

لقد وجدت أن الاتصال يتم تخزينه مؤقتًا بالفعل عند إغلاق InputStream. بمجرد إغلاق InputStream ، يتم تخزين الاتصال الأساسي. لا يمكن استخدام كائن httpurlConnection لمزيد من الطلبات ، نظرًا لأن الكائن لا يزال "متصلاً" ، أي تم تعيينه المتصلة به إلى صواب ولا يتم مسحه بمجرد وضع الاتصال مرة أخرى في المخزن المؤقت. لذلك في كل مرة يجب أن يتم إنشاء مثيل له HTTPurlConnection لنشر جديد ، ولكن سيتم إعادة استخدام اتصال TCP الأساسي ، إذا لم يتم توقيت ذلك. لذلك كانت إجابة EJP هي الوصف الصحيح. قد يكون السلوك الذي رأيته ، (إعادة استخدام اتصال TCP) على الرغم من استدعاء الاتصال الصريح () كان بسبب التخزين المؤقت الذي قام به نظام التشغيل؟ لا أعلم. آمل أن يشرح شخص يعرف. شكرًا.

كيف يمكنك "استخدام HTTP1.0" باستخدام httpurlconnection من JDK؟

وفقا للقسم "اتصالات مستمرة" من دليل Java 1.5 يمكن إيقاف تشغيل دعم الاتصالات http1.1 أو عند استخدام خاصية Java http.keepAlive (الافتراضي صحيح). علاوة على ذلك ، خاصية Java http.maxConnections يشير إلى الحد الأقصى لعدد الاتصالات (المتزامنة) لكل وجهة يجب إبقائها على قيد الحياة في أي وقت معين.

لذلك ، يمكن تطبيق "استخدام قوة HTTP1.0" للتطبيق بأكمله في وقت واحد من خلال تعيين خاصية Java http.keepAlive لخطأ.

همه. قد أفتقد شيئًا هنا (نظرًا لأن هذا سؤال قديم) ، لكن على حد علمي ، هناك طريقتان معروفين لإغلاق اتصال TCP الأساسي:

  • استخدام القوة لـ HTTP 1.0 (1.1 اتصالات مستمرة) - هذا كما هو موضح في خط طلب HTTP
  • إرسال رأس "اتصال" مع القيمة "إغلاق" ؛ هذا سوف يجبر الإغلاق كذلك.

سيؤدي التخلي عن التدفقات إلى اتصالات TCP الخاملة. يجب قراءة دفق الاستجابة بالكامل. شيء آخر أغفلته في البداية ، ورأيت التغاضي عنه في معظم الإجابات حول هذا الموضوع هو نسيان التعامل مع دفق الأخطاء في حالة استثناءات. رمز مشابه لهذا أحد التطبيقات الثابتة التي لم تكن تطلق الموارد بشكل صحيح:

HttpURLConnection connection = (HttpURLConnection)new URL(uri).openConnection();
InputStream stream = null;
BufferedReader reader = null;
try {
        stream = connection.getInputStream();
        reader = new BufferedReader(new InputStreamReader(stream, Charset.forName("UTF-8")));

        // do work on part of the input stream

} catch (IOException e) {

    // read the error stream
    InputStream es = connection.getErrorStream();
    if (es != null) {
        BufferedReader esReader = null;
        esReader = new BufferedReader(new InputStreamReader(es, Charset.forName("UTF-8")));
        while (esReader.ready() && esReader.readLine() != null) {
        }
        if (esReader != null)
            esReader.close();
    }

    // do something with the IOException
} finally {

    // finish reading the input stream if it was not read completely in the try block, then close
    if (reader != null) {
        while (reader.readLine() != null) {
        }
        reader.close();
    }

    // Not sure if this is necessary, closing the buffered reader may close the input stream?
    if (stream != null) {
        stream.close();
    }

    // disconnect
    if (connection != null) {
        connection.disconnect();
    }
}

القارئ المخزّن ليس ضروريًا تمامًا ، لقد اخترته لأن حالة الاستخدام الخاصة بي تتطلب قراءة سطر واحد في كل مرة.

أنظر أيضا: http://docs.oracle.com/javase/1.5.0/docs/guide/net/http-keepalive.html

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