2009-08-27 19 views
31

यदि मैं केवल आउटपुट स्ट्रीम पर सॉकेट के लिए लिख रहा हूं, तो क्या यह कभी भी अवरुद्ध होगा? केवल पढ़ता है ब्लॉक, सही? किसी ने मुझे बताया कि लिखना ब्लॉक कर सकता है लेकिन मुझे केवल सॉकेट की रीड विधि के लिए टाइमआउट सुविधा दिखाई देती है - Socket.setSoTimeout()जावा सॉकेट/आउटपुट स्ट्रीम लिखते हैं: क्या वे ब्लॉक करते हैं?

यह मुझे समझ में नहीं आता कि एक लेखन ब्लॉक हो सकता है।

+0

तथ्य वहाँ एक समय समाप्ति सुविधा नहीं है कि इस बात का संकेत है कि यह ब्लॉक नहीं करता ही नहीं है। एक संकेत यह है कि यह वापसी मूल्य की कमी है: यदि यह अवरुद्ध नहीं होता है, तो यह वास्तव में लिखित बाइट्स की संख्या क्यों नहीं लौटाता है? एक और संकेत सिर्फ कोशिश कर दिया जाता है। – EJP

उत्तर

45

सॉकेट पर एक लिखना भी ब्लॉक कर सकता है, खासकर यदि यह एक टीसीपी सॉकेट है। ओएस केवल एक निश्चित मात्रा में अप्रसारित (या संचरित लेकिन अनजान) डेटा बफर करेगा। यदि आप दूरस्थ ऐप की तुलना में तेज़ी से चीजें लिखते हैं तो इसे पढ़ने में सक्षम है, सॉकेट अंततः बैक अप ले जाएगा और आपकी write कॉल अवरुद्ध हो जाएंगी।

इन फॉलोअप सवालों का जवाब देते हुए:

तो वहाँ इस के लिए एक टाइमआउट सेट करने के लिए एक तंत्र है? मुझे यकीन नहीं है कि व्यवहार क्या होगा ... अगर बफर भर चुके हैं तो शायद डेटा फेंक दें? या संभवतः बफर में पुराने डेटा को हटाएं?

java.net सॉकेट पर लिखने का समय निर्धारित करने के लिए कोई तंत्र नहीं है। Socket.setSoTimeout() विधि है, लेकिन यह accept() और read() कॉल को प्रभावित करती है ... और write() कॉल नहीं करती है। जाहिर है, यदि आप एनआईओ, गैर-अवरोधन मोड और चयनकर्ता का उपयोग करते हैं, तो आप लिखने का समय प्राप्त कर सकते हैं, लेकिन यह उतना उपयोगी नहीं है जितना आप कल्पना कर सकते हैं।

एक उचित ढंग से लागू टीसीपी स्टैक buffered डेटा को तब तक नहीं छोड़ा जाता जब तक कि कनेक्शन बंद न हो जाए। हालांकि, जब आपको लिखने का समय लगता है, तो यह अनिश्चित है कि वर्तमान में ओएस-स्तरीय बफर में मौजूद डेटा को दूसरे छोर से प्राप्त किया गया है ... या नहीं। दूसरी समस्या यह है कि आप नहीं जानते कि आपके पिछले write से कितना डेटा वास्तव में ओएस-स्तरीय टीसीपी स्टैक बफर में स्थानांतरित किया गया था। स्ट्रीम * को पुनर्वित्त के लिए कुछ एप्लिकेशन स्तर प्रोटोकॉल अनुपस्थित करें, write पर टाइमआउट के बाद करने के लिए एकमात्र सुरक्षित चीज़ कनेक्शन को बंद करना है।

इसके विपरीत, यदि आप यूडीपी सॉकेट का उपयोग करते हैं, तो write() कॉल किसी भी महत्वपूर्ण अवधि के लिए अवरुद्ध नहीं होंगे। लेकिन नकारात्मक बात यह है कि अगर नेटवर्क की समस्याएं हैं या रिमोट एप्लिकेशन नहीं रख रहा है, तो फर्श पर संदेशों को छोड़ दिया जाएगा, बिना किसी सूचना के किसी अधिसूचना के। इसके अतिरिक्त, आप पाएंगे कि संदेश कभी-कभी रिमोट एप्लिकेशन को ऑर्डर के बाहर वितरित किए जाते हैं। इन मुद्दों से निपटने के लिए यह आपके (डेवलपर) पर निर्भर करेगा।

* यह सैद्धांतिक रूप से ऐसा करना संभव है, लेकिन अधिकांश अनुप्रयोगों के लिए यह पहले से ही भरोसेमंद (एक बिंदु) टीसीपी/आईपी स्ट्रीम के शीर्ष पर एक अतिरिक्त पुनर्वितरण तंत्र को लागू करने का कोई मतलब नहीं है। और अगर यह समझ में आया, तो आपको कनेक्शन से बंद होने की संभावना से निपटने की भी आवश्यकता होगी ... इसलिए यह बंद हो जाएगा।

+0

तो क्या इसके लिए टाइमआउट सेट करने के लिए एक तंत्र है? मुझे यकीन नहीं है कि इसका क्या व्यवहार होगा ... यदि बफर भर गए हैं तो शायद डेटा निकाल दें? या संभवतः बफर में पुराने डेटा को हटा दें? – jbu

+0

क्या परीक्षण के लिए इसे पुन: उत्पन्न करने का कोई तरीका है? मैं अपना आवेदन इस से फिर से भरने में सक्षम बनाना चाहता हूं। इसके लिए मुझे – Zamir

+0

AFAIK परीक्षण की आवश्यकता है, कोई सामान्य तरीका नहीं है। लेकिन आपके आवेदन की प्रकृति के आधार पर (उदा। यह किस बात से बात कर रहा है) बहुत सारे तरीके हैं। एक नया प्रश्न पूछें ... और विशिष्ट हो। –

7

ऐसा करने का एकमात्र तरीका एनआईओ और चयनकर्ताओं का उपयोग करना है।

इस बग रिपोर्ट में सूर्य/Oracle इंजीनियर से writeup देखें: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4031100

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