मेरे सुझाव के लिए, कृपया अंतिम खंड पढ़ें: "जब टाइमआउट 0 के साथ SO_LINGER का उपयोग किया जाए" ।
इससे पहले कि हम थोड़ा व्याख्यान दें:
- सामान्य टीसीपी समाप्ति
TIME_WAIT
FIN
, ACK
औरRST
सामान्य टीसीपी समाप्ति
सामान्य टीसीपी समाप्ति अनुक्रम इस तरह दिखता है (सरलीकृत):
हमारे पास दो सहकर्मी हैं: ए और बी
- एक कॉल
close()
- A
FIN
, B को भेजता है
- A
FIN_WAIT_1
राज्य में जाता है
- B प्राप्त करता है
FIN
- B
ACK
, A को भेजता है
- B
CLOSE_WAIT
राज्य में जाता है
- A प्राप्त करता है
ACK
- A
FIN_WAIT_2
राज्य में जाता है
- B कॉल करता है
close()
- B
FIN
, A को भेजता है
- B
LAST_ACK
राज्य में जाता है
- A प्राप्त करता है
FIN
- A
ACK
, B को भेजता है
- A
TIME_WAIT
राज्य में जाता है
- B प्राप्त करता है
ACK
- B
CLOSED
राज्य में जाता है - अर्थात सॉकेट टेबल से हटा दिया जाता है
समय का इंतजार
तो सहकर्मी जो समाप्ति की शुरुआत करता है - यानी close()
पहले कॉल करता है - TIME_WAIT
राज्य में समाप्त हो जाएगा ।
यह समझने के लिए कि TIME_WAIT
राज्य हमारा मित्र क्यों है , कृपया स्टीवंस एट अल (पृष्ठ 43) द्वारा "UNIX नेटवर्क प्रोग्रामिंग" तीसरे संस्करण में खंड 2.7 पढ़ें।
हालांकि, यह TIME_WAIT
एक सर्वर पर राज्य में बहुत सारे सॉकेट्स के साथ एक समस्या हो सकती है क्योंकि यह अंततः नए कनेक्शनों को स्वीकार करने से रोक सकता है।
इस समस्या के आसपास काम करने के लिए, मैंने कॉल करने से पहले टाइमआउट 0 के साथ SO_LINGER सॉकेट विकल्प सेट करने के लिए कई सुझाव दिए close()
। हालाँकि, यह एक बुरा समाधान है क्योंकि यह एक त्रुटि के साथ टीसीपी कनेक्शन को समाप्त करने का कारण बनता है।
इसके बजाय, अपने एप्लिकेशन प्रोटोकॉल को डिज़ाइन करें ताकि कनेक्शन समाप्ति हमेशा क्लाइंट की ओर से शुरू की जाए। यदि क्लाइंट को हमेशा पता रहता है कि उसने सभी शेष डेटा पढ़ लिए हैं तो वह समाप्ति क्रम शुरू कर सकता है। एक उदाहरण के रूप में, एक ब्राउज़र Content-Length
HTTP हेडर से जानता है जब उसने सभी डेटा पढ़ा है और करीब शुरू कर सकता है। (मुझे पता है कि HTTP 1.1 में यह संभव पुन: उपयोग के लिए कुछ समय के लिए खुला रखेगा, और फिर इसे बंद कर देगा।)
यदि सर्वर को कनेक्शन बंद करने की आवश्यकता है, तो एप्लिकेशन प्रोटोकॉल डिज़ाइन करें ताकि सर्वर क्लाइंट को कॉल करने के लिए कहे close()
।
कब SOUTINGER का उपयोग टाइमआउट 0 के साथ करें
फिर से, "UNIX नेटवर्क प्रोग्रामिंग" तीसरे संस्करण के पेज 202-203 के अनुसार, SO_LINGER
कॉलिंग से पहले टाइमआउट 0 के साथ सेटिंग करने close()
से सामान्य समाप्ति अनुक्रम शुरू नहीं होगा।
इसके बजाय, इस विकल्प को सेट करने और कॉल करने वाला सहकर्मी close()
एक RST
(कनेक्शन रीसेट) भेजेगा जो एक त्रुटि स्थिति को इंगित करता है और यह इसी तरह दूसरे छोर पर माना जाएगा। आप आम तौर पर "कनेक्शन रीसेट बाय पीयर" जैसी त्रुटियां देखेंगे।
इसलिए, सामान्य स्थिति में SO_LINGER
कॉल करने से पहले टाइमआउट 0 के साथ सेट करना वास्तव में एक बुरा विचार है close()
- अब से इसे गर्भपात के करीब कहा जाता है - एक सर्वर अनुप्रयोग में।
हालाँकि, कुछ परिस्थिति में ऐसा करने वाले वारंट:
- यदि आपके सर्वर एप्लिकेशन का क्लाइंट दुर्व्यवहार करता है (बार-बार अमान्य डेटा, इत्यादि लौटाता है),
CLOSE_WAIT
तो TIME_WAIT
राज्य में अटक जाने या समाप्त होने से बचने के लिए एक अपमानजनक करीबी समझ में आता है ।
- यदि आपको अपने सर्वर एप्लिकेशन को पुनरारंभ करना होगा, जिसमें वर्तमान में हजारों क्लाइंट कनेक्शन हैं, तो आप हजारों सॉकेट से बचने के लिए इस सॉकेट विकल्प पर विचार कर सकते हैं
TIME_WAIT
(जब close()
सर्वर अंत से कॉल कर रहे हों ) क्योंकि इससे सर्वर को नए क्लाइंट कनेक्शन के लिए उपलब्ध पोर्ट प्राप्त करने से रोका जा सकता है। फिर से शुरू होने के बाद।
- उपर्युक्त पुस्तक के पृष्ठ २०२ में यह विशेष रूप से कहा गया है: "कुछ विशेष परिस्थितियाँ हैं जो इस सुविधा का उपयोग करते हुए एक घनिष्ठता भेजने के लिए वारंट करती हैं। एक उदाहरण एक RS-232 टर्मिनल सर्वर है, जो
CLOSE_WAIT
एक अटक टर्मिनल पर डेटा देने की कोशिश में हमेशा के लिए लटक सकता है। यदि यह RST
लंबित डेटा को छोड़ने के लिए मिला, तो पोर्ट को ठीक से रीसेट करेगा ।
मैं इस लंबे लेख की सिफारिश करूंगा जो मेरा मानना है कि आपके प्रश्न का बहुत अच्छा उत्तर देता है।