2008-11-12 9 views
6
while (xxx) { 
    timeout.tv_sec=TIMEOUT; 
    timeout.tv_usec=0; 
    FD_ZERO(&set); 
    FD_SET(sd,&set); 

    switch (select(FD_SETSIZE,&set,NULL,NULL,&timeout)) 
    xxxxx 
} 

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

किसी के पास एक अच्छी व्याख्या है कि यह क्यों है, और इससे भी बेहतर, शायद एक सुझाव है कि इससे कैसे बचें?

+0

मुझे लगता है कि आपके द्वारा निकाले गए कुछ कोड समझने में महत्वपूर्ण हो सकते हैं कि यह किस तरह से व्यवहार कर रहा है। – SoapBox

उत्तर

12

अपने तर्कों को संशोधित करता है का चयन करें। आपको हर बार इसे फिर से शुरू करना होगा।

यदि आप ओवरहेड के बारे में चिंतित हैं, तो कर्नेल में पूर्ण FD_SET को संसाधित करने की लागत FD_ZERO की लागत से कुछ अधिक महत्वपूर्ण है। कर्नेल प्रसंस्करण को कम करने के लिए, आप केवल अपने अधिकतम एफडी में, FD_SETSZIZE नहीं, केवल पास करना चाहते हैं। अपने उदाहरण में:

switch (select((sd + 1),&set,NULL,NULL,&timeout)) 

कई एफडी साथ एक अधिक जटिल मामले के लिए, आप आम तौर पर एक अधिकतम चर को बनाए रखने के अंत:

FD_SET(sd,&set); 
if (sd > max) max = sd; 
... repeat many times... 

switch (select((max + 1),&set,NULL,NULL,&timeout)) 


आप फ़ाइल वर्णनकर्ता की एक बड़ी संख्या है और कर रहे हैं जाएगा उन्हें स्केलपिंग के ऊपरी हिस्से के बारे में चिंतित, आपको चुनने के कुछ विकल्पों को देखना चाहिए()। आप ओएस आप उपयोग कर रहे उल्लेख नहीं है, लेकिन यूनिक्स की तरह OSes के लिए देखते हैं कुछ:

    लिनक्स के लिए
  • , epoll()
  • FreeBSD/NetBSD/OpenBSD/MacOS एक्स, kqueue के लिए
  • () सोलारिस,/dev/चुनाव

एपीआई अलग हैं, लेकिन वे सभी अनिवार्य रूप से सक्रिय फ़ाइल विवरण का एक सेट बनाए रखने के लिए एक स्टेटफुल गिरी इंटरफेस रहे हैं के लिए

  • । एक बार एफडी को सेट में जोड़ा जाने के बाद, आपको उस एफडी पर घटनाओं के बारे में अधिसूचित किया जाएगा, बिना इसे लगातार पास किए।

  • +0

    एक महान उत्तर के लिए धन्यवाद :) – deadcyclo

    +1

    चुनने के विकल्प के लिए(), क्यों नहीं मतदान(), जो आपके द्वारा उल्लेख किए गए विपरीत हैं, कई इकाइयों पर समान है? – bortzmeyer

    +1

    मतदान() बेहतर है कि आपको प्रत्येक बार अपनी सरणी को फिर से शुरू करने की आवश्यकता नहीं है, लेकिन आप अभी भी प्रत्येक कॉल पर कर्नेल में और बाहर एक बड़ी संरचना की प्रतिलिपि बना रहे हैं। यदि आपके पास बहुत सारे एफडीएस हैं, तो अन्य विकल्प कर्नेल में fd सेट को संशोधित करके इस निरंतर ओवरहेड से बचते हैं। – DGentry

    7

    चुनिंदा मैन पेज पढ़ें। लौटा सेट केवल फाइल डिस्क्रिप्टर है जो उपयोग करने के लिए तैयार हैं। यदि आप सेट हैं या नहीं, तो प्रत्येक को जांचने के लिए आपको FD_ISSET का उपयोग करना होगा।

    इसका उपयोग करने से पहले हमेशा fd_set को प्रारंभ करें।

    +0

    मुझे एफडी_आईएसएसईटीटी के बारे में पता है, लेकिन मैंने इसे अभी तक शामिल नहीं किया है, क्योंकि अभी तक मैं केवल एक सॉकेट की सूची में हूं (मैं बाद में अधिक सॉकेट जोड़ रहा हूं)। तो अब fd_set पहले सेट किए बिना "पुन: उपयोग" करने में सक्षम होने का कोई तरीका है? – deadcyclo

    +0

    चुनिंदा() के दस्तावेज व्यवहार में सेट को संशोधित करना शामिल है। व्यावहारिक प्रोग्रामर उद्धृत करने के लिए, "चयन करें" टूटा नहीं है "। – bk1e

    0

    इस तरह से चुनिंदा काम करता है। यदि आपके पास एक से अधिक सॉकेट हैं, तो यह सबसे अच्छा काम करता है, और अधिक समझ में आता है। यह एक तरह का मुद्दा है: आप कई सॉकेट में चयन कर रहे हैं। यदि आप एक सॉकेट से पढ़ना चाहते हैं, तो बस इसे पढ़ें या पुनः प्राप्त करें।

    +1

    पढ़ना टाइमआउट प्रदान नहीं करता है। इसलिए चयन का उपयोग करें। + तथ्य यह है कि मैं बाद में विकास चरण में दूसरी सॉकेट जोड़ रहा हूं। – deadcyclo

    +0

    बस पेशकश विकल्प रखने के लिए: यदि एसडी एक सॉकेट है तो आप एक रीड टाइमआउट जोड़ने के लिए सेटॉकॉप (एसडी, एसओ_आरसीवीटीएमईओ, ...) का उपयोग कर सकते हैं।हालांकि अगर आप बाद में दूसरी सॉकेट जोड़ने जा रहे हैं, तो आगे बढ़ने का बेहतर विकल्प चुनें। – DGentry

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