2013-10-03 3 views
11

मैं poll() या epoll() साथ select() की तुलना में कुछ लिखने-अप देखा है, और मैं कई कई सॉकेट साथ select() का वास्तविक उपयोग पर चर्चा गाइड देखा है।सॉकेट का चयन करें() बनाम गैर ब्लॉक recv

हालांकि, मुझे लगता है कि मुझे लगता है कि recv() कॉल select() के बिना एक गैर-अवरुद्ध recv() कॉल की तुलना है। लिखने के लिए केवल 1 सॉकेट और 1 सॉकेट लिखने की स्थिति में, क्या select() कॉल का उपयोग करने के लिए कोई औचित्य है? recv() विधि को कोई डेटा उपलब्ध होने पर त्रुटि (WSAEWOULDBLOCK) को अवरुद्ध करने और वापस करने के लिए सेटअप नहीं किया जा सकता है, तो जब आपके पास कोई अन्य सॉकेट जांचने के लिए select() पर कॉल करने के लिए परेशान क्यों है? क्या गैर-अवरुद्ध recv() बहुत धीमी है?

+0

शायद यह आपके कार्यान्वयन के सभी विवरण हैं। क्या तुमने कोशिश की? –

+0

जब आप लगातार पढ़ने के लिए कोई डेटा नहीं रखते हैं तो आप क्या करने जा रहे हैं? लूप हमेशा के लिए? या चयन या मतदान या एपोल का उपयोग करें ?? अवरुद्ध या अनब्लॉक करने के बावजूद, आपको किसी भी तरह से डेटा की प्रतीक्षा करनी होगी। – goji

+0

हाँ, जैसा कि @ ट्रॉय ने कहा था, इस तरह आप सक्रिय प्रतीक्षा लागू करेंगे - जिसका मतलब प्रोसेसर के लिए कोई दया नहीं है, जब पढ़ने के लिए कुछ भी नहीं है। – zoska

उत्तर

9

आप सॉकेट पर डेटा की प्रतीक्षा के लिए किसी अन्य माध्यम के बिना रिकॉर्ड्स को रिकॉव करना नहीं चाहते हैं क्योंकि आप असीम रूप से सीपीयू समय खा रहे हैं।

यदि आपके पास जांच करने के लिए कोई अन्य सॉकेट नहीं है और उसी धागे में कुछ और करने के लिए नहीं है, तो पढ़ने के लिए एक अवरुद्ध कॉल सबसे कुशल समाधान होने की संभावना है। हालांकि ऐसी स्थिति में, इसकी दक्षता पर विचार करना समयपूर्व अनुकूलन होना है।

सॉकेट गिनती बढ़ने के साथ ही इस तरह के विचार केवल खेल में आते हैं।

गैर-ब्लॉकिंग कॉल केवल एक थ्रेड पर एकाधिक सॉकेट को संभालने के संदर्भ में तेज़ी से हैं।

+1

मैं इसे आपकी प्रतिक्रिया से और प्रतिक्रियाओं से नीचे लेता हूं कि एक लूपिंग आरईवी() अधिक सीपीयू गहन है, जिससे मुझे संदेह होता है कि एक लूप में चयन() वास्तव में थ्रेड को निलंबित करता है? यह बिल्कुल अंतर हो सकता है जिसके बारे में मैं सोच रहा था। इसके अलावा, यदि यह सच है, तो मुझे संदेह होगा कि यह केवल समय अवधि के लिए निलंबित है, जो अवरुद्ध कॉल में चयन करता है? यह सीखना, आप 2 सॉकेट थ्रेड (इनपुट के लिए 1, आउटपुट के लिए 1) का सुझाव कैसे देंगे, जिसमें आपको अधिकतम गति पर प्रक्रिया करने के लिए दोनों की आवश्यकता होती है, लेकिन उत्पादन केवल तभी होता है जब कतार से नया डेटा उपलब्ध हो ? –

+0

'चयन()' को कॉल करने से पहले आप इसकी संरचनाओं (बिट्स) को पॉप्युलेट करते हैं। यदि डेटा को लिखे जाने के लिए तैयार buffered है, तो आप आउटपुट सॉकेट को लिखने के बिटसेट में सेट करते हैं, इनपुट सॉकेट हमेशा रीड बिटसेट में सेट किया जाएगा। यह बहुत विशिष्ट चयन उपयोग है और Google पर कई उदाहरण हैं। – goji

+1

यह पुस्तक सॉकेट बाइबल इमो है: http://www.amazon.com/UNIX-Network- प्रोग्रामिंग- नेटवर्किंग- सॉकेट्स/डीपी/013490012 एक्स – goji

3

यदि कोई डेटा उपलब्ध नहीं है, और आप गैर-अवरुद्ध आईओ, recv() का उपयोग तुरंत वापस कर देंगे। फिर कार्यक्रम क्या करना चाहिए? डेटा उपलब्ध होने तक आपको recv() को लूप में कॉल करने की आवश्यकता होगी - यह केवल बहुत अधिक कारण के लिए CPU का उपयोग करता है।

recv() पर स्पिनिंग और उस तरीके से जलती हुई सीपीयू बहुत अवांछनीय है; आप प्रक्रिया को तब तक इंतजार करना चाहते हैं जब तक कि डेटा उपलब्ध न हो जाए और जागृत हो जाएं; यही select()/poll() है और इसी तरह करता है।

और सीपीयू को जलाने के लिए लूप में sleep() या तो कोई अच्छा समाधान नहीं है। आप प्रसंस्करण में उच्च विलंबता पेश करेंगे क्योंकि डेटा डेटा उपलब्ध होने पर डेटा को संसाधित करने में सक्षम नहीं होगा।

5

select() और दोस्तों ने आपको वर्कफ़्लो को इस तरह से डिज़ाइन करने दिया है कि एक सॉकेट की धीमी गति उस गति को बाधित नहीं करती है जिस पर आप दूसरी सेवा कर सकते हैं। कल्पना करें कि डेटा प्राप्त करने वाली सॉकेट से तेज़ी से आता है और आप जितनी जल्दी हो सके इसे स्वीकार करना चाहते हैं और मेमोरी बफर में स्टोर करना चाहते हैं। लेकिन भेजने वाली सॉकेट धीमी है। जब आप ओएस के भेजने वाले बफर भर चुके हैं और send() ने आपको EWOULDBLOCK दिया है, तो आप सॉकेट प्राप्त करने और भेजने दोनों पर प्रतीक्षा करने के लिए चुनिंदा() जारी कर सकते हैं। select() तब प्राप्त होगा जब प्राप्तकर्ता सॉकेट पर कोई नया डेटा आ जाएगा, या कुछ बफर मुक्त हो जाते हैं और आप भेजने वाली सॉकेट में अधिक डेटा लिख ​​सकते हैं, जो भी पहले होता है।

बेशक select() के लिए एक और यथार्थवादी उपयोग केस तब होता है जब आपके पास पढ़ने और/या लिखने के लिए एकाधिक सॉकेट होते हैं, या जब आपको दोनों दिशाओं में अपने दो सॉकेट के बीच डेटा पास करना होगा।

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

दूसरी ओर, select() का उपयोग न करने वाले सॉकेट को गैर-अवरुद्ध करना और reason explained by @Troy की वजह से लगभग कभी सलाह नहीं दी जाती है।

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