2012-06-05 18 views
5

मेरे पास एक तृतीय पक्ष लाइब्रेरी है जो HTTP सर्वर के रूप में कार्य करती है। मैं इसे एक पता और बंदरगाह पास करता हूं, जिसका उपयोग यह आने वाले कनेक्शन सुनने के लिए करता है। यह लाइब्रेरी इस तरह से सुनती है कि इसे बंदरगाह और पते का अनन्य उपयोग प्राप्त नहीं होता है। नतीजतन, मैं एक ही बंदरगाह पर कई बार सुन सकता हूं।मैं कैसे जांचूं कि एक टीसीपी पोर्ट पहले ही सुना जा रहा है या नहीं?

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

मैं HTTP सर्वर के कोड को नहीं बदल सकता और HTTP सर्वर मुझे चेतावनी नहीं देगा अगर यह पोर्ट को मैं नहीं सुन सकता, तो मुझे यह जांचने में सक्षम होना चाहिए कि प्रत्येक HTTP सर्वर शुरू करने से पहले पोर्ट पहले से उपयोग में है या नहीं । मैंने यह जांचने की कोशिश की है कि क्या एसओआरयूयूएसएडीडीआरडी सेट के साथ अपने स्वयं के सॉकेट को FALSE और SO_EXCLUSIVEADDRUSE पर सेट किया गया है, लेकिन बाध्य और सुनो कॉल दोनों सफल होते हैं जब एक मौजूदा HTTP सर्वर पहले से ही उस पोर्ट पर सुन रहा है।

यह HTTP सर्वर इस प्रभाव को कैसे प्राप्त कर रहा है, और मैं इस तरीके से एक बंदरगाह की सुनवाई कैसे कर सकता हूं?

+0

क्या कोई कारण है कि आपको इस विशेष HTTP सर्वर लाइब्रेरी का उपयोग करना है? यह देखते हुए कि यह टूटा हुआ है, और आपके पास पर्याप्त नियंत्रण नहीं है या यह भी पता लगाने के लिए कि यह काम करने के लिए क्या कर रहा है, यह पता लगाने के लिए, स्विचिंग एक बहुत अच्छा विचार प्रतीत होता है। – abarnert

+0

जिज्ञासा से, कौन सा पुस्तकालय है? –

+0

"यह लाइब्रेरी इस तरह से सुनती है कि इसे बंदरगाह और पते के अनन्य उपयोग को प्राप्त नहीं होता है"। टीसीपी में यह संभव नहीं है। टीसीपी में संभव है कि पोर्ट-शेयरिंग का एकमात्र रूप अलग-अलग स्थानीय आईपी पते और उसी पोर्ट नंबर पर बाध्यकारी है। आपको फिर से जांच करने और फिर अपने प्रश्न को दोबारा सुधारने की जरूरत है। – EJP

उत्तर

4

त्वरित और गंदा विधि स्थानीयहोस्ट पर बंदरगाह पर connect() करने का प्रयास करेगी। यदि connect() कॉल सफल होता है, तो आप जानते हैं कि पोर्ट वर्तमान में सुन रहा है (जिसे किसी भी कनेक्शन से प्राप्त किया गया है)। यदि कनेक्ट कॉल विफल रहता है (विशेष रूप से ECONNREFUSED के साथ) तो आप सुनिश्चित हो सकते हैं कि कोई भी उस बंदरगाह पर नहीं सुन रहा है।

बेशक, यहां एक दौड़ की स्थिति है: उपरोक्त परीक्षण चलाने के तुरंत बाद बंदरगाह को पकड़ने और बंदरगाह को पकड़ने से कुछ भी नहीं रोक रहा है, लेकिन इससे पहले कि आप बंदरगाह पर बाध्यकारी हो जाएं। तो आपको परीक्षण के परिणाम को एक पूर्ण नियम की तुलना में अधिक संकेत के रूप में लेना चाहिए, और (उम्मीद है कि) इसे बाद में संभालने का कोई तरीका है यदि आप बाद में पता लगाते हैं कि बंदरगाह सभी के बाद उपयोग में है।

+0

उनके इच्छित परीक्षण कोड में एक ही दौड़ की स्थिति होगी (या, बल्कि, यदि यह काम करता है तो उसी दौड़ की स्थिति होगी ...)। और वास्तव में, उसके डिजाइन को देखते हुए, इससे बचने का कोई तरीका नहीं है। – abarnert

+0

(ऊपर बता रहा है कि मैंने दौड़ की स्थिति के बावजूद आपको +1 क्यों दिया, आपके उत्तर या उससे कुछ भी असहमत नहीं।) – abarnert

2

0. पोर्ट नंबर का उपयोग करें। ओएस एक मुफ्त बंदरगाह लेगा।

+0

मेरे पास HTTP सर्वर की पहुंच नहीं है आंतरिक सॉकेट, इसलिए यदि मैं पोर्ट के रूप में 0 पास करता हूं, तो मैं ओएस को पोर्ट बंद नहीं कर सकता। –

+0

फिर पोर्ट 0 का उपयोग करके एक सॉकेट बांधें, आपके लिए चुने गए पोर्ट नंबर को खोजने के लिए 'getockaddr' का उपयोग करें, उसी पोर्ट का उपयोग करके एक HTTP सर्वर प्रारंभ करें, और फिर अस्थायी सॉकेट बंद करें। –

1

http://msdn.microsoft.com/en-us/library/windows/desktop/ms740621(v=vs.85).aspx बताता है कि विभिन्न विकल्प कैसे इंटरैक्ट करते हैं।

आपने हमें अपने उपयोग के मामले में क्या हो रहा है, यह बताने के लिए हमें लगभग पर्याप्त जानकारी नहीं दी है, लेकिन मैं एक मनमाने ढंग से उपयोग के मामले में काम कर सकता हूं जो आप देख रहे हैं।

मान लें कि आप विन 2003 या बाद में हैं, और आपका प्राथमिक एनआईसी 10.0.0.1 है, और सब कुछ एक ही उपयोगकर्ता खाते के तहत चल रहा है।

आपके ऐप का पहला उदाहरण आता है, और आपका टेस्ट कोड SO_EXCLUSIVEADDREUSE के साथ 10.0.0.1:12345 को बांधने का प्रयास करता है। बेशक यह काम करता है।

आप सॉकेट बंद करते हैं, फिर पोर्ट 12345 को सुनने के लिए HTTP सर्वर को बताएं। यह SO.0USEADDR के साथ 0.0.0.0:12345 को बांधता है, जो निश्चित रूप से काम करता है।

अब आपके ऐप का दूसरा उदाहरण आता है, और आपका टेस्ट कोड SO_EXCLUSIVEADDREUSE के साथ 10.0.0.1:12345 को बांधने का प्रयास करता है। एमएसडीएन लेख में चार्ट के मुताबिक, यह काम करता है।

आप सॉकेट बंद करते हैं, फिर पोर्ट 12345 को सुनने के लिए HTTP सर्वर को बताएं। यह SO.0USEADDR के साथ 0.0.0.0:12345 को बांधता है, जो काम करता है।

यदि यह समस्या है, तो यह मानते हुए कि आप HTTP सर्वर को किसी विशिष्ट पते को बांधने के लिए नहीं प्राप्त कर सकते हैं, तो आप अपने परीक्षण कोड में 0.0.0.0 का उपयोग कर चीजों को हल कर सकते हैं।(बेशक अगर यह अन्य सैकड़ों संभावित समस्याओं में से एक है, तो वह समाधान काम नहीं करेगा।)

यदि आपको नहीं पता कि सॉकेट विकल्प, पता, आदि HTTP सर्वर का उपयोग कर रहा है, और नहीं स्रोत है, बस इसे डीबगर में चलाएं और प्रासंगिक कॉल को तोड़ दें।

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

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