2012-06-27 7 views
9

मैं एंड्रॉयड (2.3.x) पर एक ThreadSafeClientConnManager साथ DefaultHttpClient उपयोग कर रहा हूँ एक मेरी बाकी सर्वर से HTTP अनुरोध भेजने के लिए (एम्बेडेड जेट्टी)।DefaultHttpClient आधा बंद सॉकेट पर डेटा क्यों भेजता है?

निष्क्रिय समय की ~ 200 सेकंड के बाद, सर्वर एक [फिन] के साथ TCP कनेक्शन बंद कर देता है। एंड्रॉइड क्लाइंट एक [एसीके] के साथ प्रतिक्रिया करता है। यह सॉकेट को आधे बंद राज्य में छोड़ देना चाहिए (सर्वर अभी भी सुन रहा है, लेकिन डेटा नहीं भेज सकता है)।

मैं उम्मीद होती है कि जब ग्राहक फिर से उस कनेक्शन का उपयोग करने (HttpClient.execute के माध्यम से), DefaultHttpClient आधा बंद स्थिति का पता लगाने जाएगा कोशिश करता है, ग्राहक के पक्ष (इस प्रकार भेजने यह है पर सॉकेट बंद [फिन/एसीके] को अंतिम रूप देने बंद करें), और अनुरोध के लिए एक नया कनेक्शन खोलें। लेकिन, रगड़ है।

इसके बजाय, यह आधा बंद सॉकेट से अधिक नए HTTP अनुरोध भेजता है। भेजने के बाद ही आधे बंद राज्य का पता चला है और सॉकेट क्लाइंट-साइड पर बंद हो गया है (सर्वर पर भेजे गए [FIN] के साथ)। बेशक, सर्वर अनुरोध का जवाब नहीं दे सकता (यह पहले से ही [एफआईएन] भेज चुका था), इसलिए ग्राहक सोचता है कि अनुरोध विफल हुआ और स्वचालित रूप से एक नई सॉकेट/कनेक्शन के माध्यम से पुनः प्रयास करता है।

अंतिम परिणाम है कि सर्वर को देखता है और अनुरोध की दो प्रतियां प्रक्रियाओं है।

इसे ठीक करने के तरीके पर कोई विचार? (मेरा सर्वर दूसरी प्रतिलिपि के साथ सही चीज करता है, लेकिन मुझे परेशान है कि पेलोड दो बार प्रसारित किया जाता है।)

डिफ़ॉल्ट नहीं होना चाहिए डिफ़ॉल्ट एचटीपी क्लाइंट का पता लगाना चाहिए कि सॉकेट बंद था जब यह पहली बार नई HTTP पैकेट लिखने की कोशिश करता था, तुरंत उस सॉकेट को बंद करें, और एक नया शुरू करें? सर्वर के एक [एफआईएन] भेजे जाने के बाद सॉकेट मिनटों पर एक नया HTTP अनुरोध कैसे भेजा जाता है, इस बारे में मैं परेशान हूं।

+0

'AndroidHttpClient' ठीक उसी व्यवहार (एक' ThreadSafeClientConnManager' साथ अर्थात एक 'DefaultHttpClient' धागा सुरक्षा सुनिश्चित करने के) करता है ... शायद आप कि उपयोग करने का प्रयास कर सकते हैं? मुझे सॉकेट कनेक्शन कैसे काम करता है, इस बारे में विवरण के बारे में बहुत कुछ नहीं पता, लेकिन सिर्फ एक सुझाव ... –

उत्तर

5

यह जावा में अवरुद्ध I/O की एक सामान्य सीमा है। सॉकेट से पढ़ने की कोशिश के अलावा विपरीत एंडपॉइंट ने कनेक्शन बंद कर दिया है या नहीं, यह पता लगाने का कोई तरीका नहीं है। Apache HttpClient इस समस्या को इतनी पुरानी कनेक्शन जांच को नियोजित करके काम करता है जो अनिवार्य रूप से एक बहुत ही संक्षिप्त पढ़ा ऑपरेशन है। हालांकि, चेक कर सकते हैं और अक्सर अक्षम किया जाता है। असल में यह अक्सर सलाह दी जाती है कि यह अतिरिक्त विलंबता के कारण इसे अक्षम कर दिया जाए। मुझे नहीं पता कि एंड्रॉइड के साथ भेजे गए एचटीपी क्लाइंट का संस्करण वास्तव में इस संबंध में कैसे व्यवहार करता है लेकिन आप उचित कॉन्फ़िगरेशन पैरामीटर का उपयोग करके चेक को स्पष्ट रूप से सक्षम करने का प्रयास कर सकते हैं।

इस समस्या का एक बेहतर समाधान कनेक्शन पूल से कनेक्शन को बेदखल कर सकता है जो निष्क्रियता की अवधि के बाद किसी विशेष अवधि (150 सेकंड कहें) पर निष्क्रिय हो गया है।

http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html#d5e652

+0

धन्यवाद। मेरे पास पुराने कनेक्शन चेक सक्षम हैं, लेकिन चेक अभी भी एंड्रॉइड पर नहीं किया गया है। यह एक स्टैंडअलोन, वेनिला एचटीपी क्लाइंट जार के साथ किया जाता है। हो सकता है कि Android टीम वास्तव में HttpClient innards के साथ गड़बड़ हो जब वे एंड्रॉइड repos में आयात किया। मुझे लगता है कि मैं निष्क्रिय कनेक्शन बेदखल थ्रेड सुझाव ले जाऊंगा। –

+1

@ डेविड बी। एडन्रॉइड के साथ Google जहाजों का एक कांटा अपाचे एचटीपी क्लाइंट के बेहद पुराने (पूर्व बीटा 4.0) संस्करण पर आधारित है। यह व्यवहार्य Google इंजीनियरों ने पुरानी कनेक्शन जांच हटा दी हो सकती है। – oleg

संबंधित मुद्दे