2009-01-19 21 views
8

मैं लिनक्स सिस्टम पर काम कर रहा हूं (2.6.20 कर्नेल के साथ उबंटू 7.04 सर्वर)।यूडीपी सॉकेट पर चयन सॉकेट बंद होने पर समाप्त नहीं होता है - मैं क्या गलत कर रहा हूं?

मैं एक कार्यक्रम एक धागा (thread1) है कि पठनीय बनने के लिए UDP सॉकेट के लिए एक चयन पर इंतजार कर मिल गया है। मैं केवल एक कॉलआउट चाहता हूं क्योंकि मैं केवल एक कॉलआउट चाहता हूं क्योंकि मैं केवल एक को पढ़ने के बजाय चयन (मेरे सॉकेट के साथ एकल readfd और एकल वगैरह के रूप में) का उपयोग कर रहा हूं।

किसी अन्य धागे से, मैं सॉकेट बंद करता हूं और सॉकेट बंद करता हूं। यदि मैं ऐसा करता हूं तो थ्रेड 1 को रिकॉर्फ़ में अवरुद्ध कर दिया जाता है, तो रिक्रॉर्फ़ तुरंत समाप्त हो जाएगा। यदि मैं ऐसा करता हूं, तो थ्रेड 1 को टाइमआउट के साथ चयन में अवरुद्ध कर दिया जाता है, तो चयन तुरंत समाप्त नहीं होगा, लेकिन आखिरकार समय-समय पर ठीक हो जाएगा।

किसी को भी मुझे बता सकते हैं क्यों यह है कि चयन जैसे ही सॉकेट बंद कर दिया है से बाहर निकलने नहीं करता है? क्या यह अपवाद नहीं है? मैं देख सकता हूं कि यह कहां पठनीय नहीं है (जाहिर है), लेकिन यह बंद है, जो प्रतीत होता है।

struct timeval to; 
to.tv_sec = timeout_ms/1000;// just the seconds portion 
to.tv_usec = (timeout_ms%1000)*1000;// just the milliseconds 
            // converted to microseconds 

// watch our one fd for readability or 
// exceptions. 
fd_set readfds, exceptfds; 
FD_ZERO(&readfds); 
FD_SET(m_sockfd, &readfds); 
FD_ZERO(&exceptfds); 
FD_SET(m_sockfd, &exceptfds); 

int nsel = select(m_sockfd+1, &readfds, NULL, &exceptfds, &to); 

अद्यतन:

m_sockfd = socket(PF_INET, SOCK_DGRAM, 0); 
struct sockaddr_in si_me; 
memset((char *) &si_me, 0, sizeof(si_me)); 
si_me.sin_family = AF_INET; 
si_me.sin_port = htons(port); 
si_me.sin_addr.s_addr = htonl(INADDR_ANY); 
if (bind(m_sockfd, (struct sockaddr *)(&si_me), sizeof(si_me)) < 0) 
{ 
// deal with error 
} 

यहाँ चुनिंदा बयान है कि thread1 निष्पादित करता है:

यहाँ (सभी त्रुटि इसे आसान बनाने के लिए हटा दिया हैंडलिंग) सॉकेट के उद्घाटन के अवसर है जाहिर है (जैसा कि नीचे वर्णित), सॉकेट बंद करना एक असाधारण स्थिति नहीं है (चयन के दृष्टिकोण से)। मुझे लगता है कि मुझे क्या जानने की ज़रूरत है: क्यों? और, क्या यह जानबूझकर है?

मैं वास्तव में इस चयन व्यवहार के पीछे की सोच को समझने के लिए, क्योंकि यह मेरी उम्मीदों के लिए काउंटर लगता है चाहता हूँ। इस प्रकार, मुझे स्पष्ट रूप से मेरी सोच को समायोजित करने की आवश्यकता है कि टीसीपी स्टैक कैसे काम करता है। कृपया मुझे यह समझाओ।

उत्तर

4

शायद आपको चुनने के लिए कुछ और उपयोग करना चाहिए। शायद एक पाइप या ऐसा कुछ।

+0

यह एक अच्छा समाधान होगा। सॉकेट और पाइप दोनों पर चयन का इंतजार करें, और दूसरा थ्रेड पाइप को लिखने के लिए चयन करने के लिए लिख देगा। –

+0

यह काम करेगा और संभवतः मैं समाप्त हो जाऊंगा। मैं बस किसी भी अतिरिक्त चलती भागों से बचना चाहता था। धन्यवाद! –

4

यूडीपी एक कनेक्शन रहित प्रोटोकॉल है। चूंकि कोई कनेक्शन नहीं है, इसलिए कोई भी टूटा नहीं जा सकता है, इसलिए उपभोक्ता को यह नहीं पता कि निर्माता कभी भी फिर से नहीं भेजेगा।

आप निर्माता संदेश एक "धारा के अंत" भेजें बना सकता है, और उपभोक्ता इसे प्राप्त करने पर समाप्त होता है।

+1

सभी सही, और सही और व्यवहार्य कामकाज, लेकिन: जब मैं सॉकेट बंद करता हूं तो रिकॉर्फ़ समाप्त होता है। चयन क्यों नहीं करता है? मैं वास्तव में उलझन में हूं कि सॉकेट को बंद करने से अपवाद उत्पन्न नहीं होता है जो चयन को समाप्त करता है। –

+0

मेरा मानना ​​है कि आपने इस सवाल को गलत समझा: दो धागे दो यूडीपी सॉकेट में हेरफेर नहीं कर रहे हैं। ** केवल एक यूडीपी सॉकेट ** है। – curiousguy

2

मुझे लगता है कि सबसे स्पष्ट समाधान यह है कि बंद होने पर असाधारण स्थिति नहीं माना जाता है। मुझे लगता है कि समस्या की जड़ यह है कि आप वास्तव में select के दर्शन को स्वीकार नहीं कर रहे हैं। पृथ्वी पर क्यों आप किसी अन्य धागे में सॉकेट के साथ झुका रहे हैं, जो आपदा के लिए नुस्खा की तरह लगता है।

+0

प्रगति में प्रतीक्षा रोकने के प्रयोजनों के लिए, मैं किसी अन्य थ्रेड से सॉकेट के साथ एकमात्र चीज बंद कर देता हूं। इस तरह से मैं चुनिंदा टाइमआउट समाप्त होने से पहले बाहर निकलने के लिए अपना प्रोग्राम प्राप्त कर सकता हूं। –

2

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

3

आप धागा जो का चयन करें() EINTR साथ वापस जाने के लिए कारण होगा के लिए एक संकेत (जैसे USR2) नहीं भेजा जा सका? फिर सिग्नल हैंडलर में एक झंडा सेट करता है जो इसे चुनने() को पुनरारंभ नहीं करता है?

कि एकाधिक फ़ाइल वर्णनकर्ता पर इंतजार की आवश्यकता को दूर होता है और यह को मारने के लिए एक पाइप का उपयोग कर की तुलना में बहुत क्लीनर लगता है।

+0

हां, यह काम करेगा, हालांकि इस विशेष मामले में मुझे नहीं लगता कि मैं आंतरिक रूप से सिग्नल का उपयोग कर सकता हूं (हमारे लाइब्रेरी उपयोग में बुरी तरह से लिखित आधार कक्षाओं में से कुछ और/या अजीब तरीके से ब्लॉक सिग्नल)। अगर मैं अंतर्निहित पुस्तकालयों को साफ कर सकता हूं, तो मैं इसे किसी बिंदु पर आजमा सकता हूं। –

0

आपका कोड मूल रूप से टूटा हुआ है।इस गलती पर भिन्नताएं आम हैं और अतीत में भारी सुरक्षा प्रभावों के साथ गंभीर बग पैदा हुई हैं। यहां आप जो खो रहे हैं:

जब आप सॉकेट को बंद करने के लिए जाते हैं, तो यह पता नहीं है कि अन्य धागा select में अवरुद्ध है या select में अवरुद्ध करने के बारे में है। उदाहरण के लिए, निम्नलिखित पर विचार करें:

  1. धागा select पर कॉल करने के लिए जाता है, लेकिन निर्धारित नहीं होता है।
  2. आप सॉकेट बंद करते हैं।
  3. थ्रेड में आपका कोड अनजान है (शायद यह प्लेटफॉर्म के आंतरिक मेमोरी प्रबंधन या आंतरिक लॉगिंग का हिस्सा है) लाइब्रेरी एक सॉकेट खोलती है और आपके द्वारा बंद सॉकेट के समान पहचानकर्ता प्राप्त करती है।
  4. धागा अब select में जाता है, लेकिन यह लाइब्रेरी द्वारा खोले गए सॉकेट पर select आईएनजी है।
  5. आपदा हमले।

आप इसे का उपयोग करते समय एक और धागा है एक संसाधन को रिहा करने का प्रयास करना होगा नहीं, या हो सकता है,।

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