2009-12-18 4 views
5

से बचें मैं क्लाइंट में TIME_WAIT से बचने की कोशिश कर रहा हूं। मैं कनेक्ट करता हूं और फिर O_NONBLOCK और SO_REUSEADDR सेट करता हूं। जब तक यह 0 लौटाता है तब तक मैं पढ़ता हूं। जब रिटर्न 0 पढ़ता है, तो त्रुटि भी 0 है। मैंने इसे एक संकेत के रूप में व्याख्या की है कि सर्वर ने कनेक्शन बंद कर दिया है। हालांकि, अगर मैं करीब कॉल करता हूं, तो सॉकेट को netstat द्वारा पुष्टि के अनुसार TIME_WAIT पर सेट किया जाता है।टाइम_WAIT

चूंकि मैं एक ही मेजबान/बंदरगाह के साथ कई कनेक्शन करता हूं, इसलिए अंततः मैं "उपयोग में पता" त्रुटियों को देखना शुरू करता हूं (http://hea-www.harvard.edu/~fine/Tech/addrinuse.html देखें)।

क्या मुझे रिटर्न 0 पढ़ने के बाद बंद करना चाहिए? अगर मैं फ़ाइल डिस्क्रिप्टर जारी नहीं किया जाएगा?

+0

sidenote: जब पढ़ा रिटर्न 0 errno मूल्य अपरिभाषित है - errno केवल विफलता के बाद परिभाषित किया गया है। –

उत्तर

5

वह पक्ष जिसने कनेक्शन बंद करने की शुरुआत की है वह वह है जो TIME_WAIT स्थिति में समाप्त होता है। read() लौटने वाला 0 इंगित करता है कि सर्वर ने सॉकेट को पहले बंद कर दिया है, इसलिए हाँ - इसका मतलब यह होना चाहिए कि TIME_WAIT सर्वर की तरफ समाप्त होता है, और ग्राहक LAST_ACK से गुजरता है।

दिन के अंत में, आप TIME_WAIT स्थिति से बच नहीं सकते हैं। यहां तक ​​कि यदि आप इसे क्लाइंट से सर्वर पक्ष में ले जाने में सफल होते हैं, तो भी आप (server host, server port, client host, client port) टुपल का पुन: उपयोग नहीं कर सकते हैं जब तक कि TIME_WAIT खत्म नहीं हो जाता है (भले ही यह किस तरफ है)।

के बाद से है कि टपल के तीन भाग अपने परिदृश्य (server host, server port, client host) में तय कर रहे हैं, तो आप वास्तव में केवल इन विकल्प हैं: अधिक ग्राहक बंदरगाहों उपलब्ध बनाने के लिए

  • प्रयास करें। कुछ ऑपरेटिंग सिस्टम डिफ़ॉल्ट रूप से "क्षणिक बंदरगाहों" के लिए उपलब्ध बंदरगाहों की एक छोटी सी श्रृंखला का उपयोग करते हैं (मुझे इस संबंध में ओएसएक्स के बारे में निश्चित नहीं है)। यदि ऐसा है, तो देखें कि क्या आप ओएस में कॉन्फ़िगरेशन ट्वीक के साथ रेंज बदल सकते हैं, या वैकल्पिक रूप से कनेक्शन काम करने तक लूप में bind()/connect() के साथ एक कार्यशील पोर्ट के लिए एप्लिकेशन खोज कर सकते हैं।

  • अपने क्लाइंट पर एकाधिक आईपी पते का उपयोग करके client host मानों की संख्या का विस्तार करें। आपको विशेष रूप से हालांकि इन आईपी पते में से एक को bind() आवेदन करना होगा।

  • सर्वर पर एकाधिक बंदरगाहों और/या आईपी पते का उपयोग करके server host/server port मानों की संख्या का विस्तार करें। क्लाइंट को कनेक्ट करने के लिए एक को चुनना होगा (राउंड रॉबिन, यादृच्छिक, आदि)।

  • शायद यह सबसे अच्छा विकल्प है, यदि यह करने योग्य है: अपने प्रोटोकॉल को दोबारा दोहराएं ताकि कनेक्शन समाप्त हो जाएं, लेकिन एक "निष्क्रिय" स्थिति में जाएं ताकि उन्हें बाद में फिर से उपयोग किया जा सके, बजाय नया कनेक्शन (जैसे HTTP को जीवित रखें)।

+0

पुराने प्रश्न पर टिप्पणी करने के लिए खेद है, लेकिन इस उत्तर का पहला अनुच्छेद नहीं पढ़ता है "कनेक्शन की समाप्ति को शामिल करने वाला पक्ष वह है जो TIME_WAIT स्थिति में समाप्त होता है"? मुझे लगता है कि कुछ किताबों में यह पढ़ना याद है, और ऐसा लगता है कि http://hea-www.harvard.edu/~fine/Tech/addrinuse.html – zentrunix

+0

@ जोसेक्स में क्या शामिल है, हां, आप ' री राइट। – caf

1

बाद में उसी पृष्ठ पर वे SO_REUSEADDR का उल्लेख करते हैं। यही आपको चाहिए। जब आप शून्य लौटाते हैं तो आप निश्चित रूप से पठन फ़ाइल डिस्क्रिप्टर को बंद करना चाहते हैं।

+0

क्षमा करें। मैं यह जोड़ना भूल गया कि मैं SO_REUSEADDR सेट करता हूं। इस आलेख में देखें कि जब आप उसी पोर्ट/होस्ट से कनेक्ट होते हैं तो यह उपयोग त्रुटियों में पता को रोकता नहीं है। – richcollins

0

क्लाइंट की तरफ SO_REUSEADDR स्थापना सर्वर साइड मदद नहीं करता है जब तक कि यह भी सेट SO_REUSEADDR

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