TCP विकल्प SO_LINGER (0) कब आवश्यक है?


95

मुझे लगता है कि मैं विकल्प के औपचारिक अर्थ को समझता हूं। कुछ विरासत कोड मैं अब संभाल रहा हूं, विकल्प का उपयोग किया जाता है। ग्राहक RST के बारे में शिकायत करता है कि वह अपनी ओर से कनेक्शन बंद होने पर अपनी ओर से फिन की प्रतिक्रिया के रूप में।

मुझे यकीन नहीं है कि मैं इसे सुरक्षित रूप से निकाल सकता हूं, क्योंकि मुझे समझ नहीं आता कि इसका उपयोग कब किया जाना चाहिए।

क्या आप कृपया एक उदाहरण दे सकते हैं कि विकल्प की आवश्यकता कब होगी?


1
आपको इसे हटा देना चाहिए। इसका उपयोग उत्पादन कोड में नहीं किया जाना चाहिए। केवल एक बार जब मैंने इसे देखा तो इसका इस्तेमाल एक अमान्य बेंचमार्क के परिणामस्वरूप हुआ।
लोर्न

जवाबों:


82

SO_LINGERशून्य पर टाइमआउट सेट करने का विशिष्ट कारण TIME_WAITराज्य में बैठे बड़ी संख्या में कनेक्शन से बचना है , जो सभी उपलब्ध संसाधनों को सर्वर पर बांधता है।

जब टीसीपी कनेक्शन को साफ बंद कर दिया जाता है, तो अंत ("सक्रिय करीबी") को शुरू करने वाला अंत TIME_WAITकई मिनट तक बैठे कनेक्शन के साथ समाप्त होता है । इसलिए यदि आपका प्रोटोकॉल वह है जहां सर्वर कनेक्शन को चालू करता है, और बहुत बड़ी संख्या में अल्पकालिक कनेक्शन शामिल करता है, तो यह इस समस्या के लिए अतिसंवेदनशील हो सकता है।

यह एक अच्छा विचार नहीं है, हालांकि - TIME_WAITएक कारण के लिए मौजूद है (यह सुनिश्चित करने के लिए कि पुराने कनेक्शन से आवारा पैकेट नए कनेक्शन में हस्तक्षेप नहीं करते हैं)। यह एक बेहतर विचार है कि अपने प्रोटोकॉल को फिर से डिज़ाइन करें जहां ग्राहक कनेक्शन को चालू करता है, यदि संभव हो तो।


3
मैं पूरी तरह सहमत हूँ। मैंने एक मॉनिटरिंग एप्लिकेशन देखा है जो कई (कुछ हज़ारों कम समय तक चलने वाले कनेक्शन हर X सेकंड में) शुरू कर रहा था, और इसमें प्रोबेल को बड़ा (एक हज़ार कनेक्शन अधिक) करने की आवश्यकता थी। मुझे पता नहीं क्यों, लेकिन आवेदक गैर उत्तरदायी था। किसी ने SO_LINGER = true, TIME_WAIT = 0 को OS संसाधनों को जल्दी से मुक्त करने का सुझाव दिया, और छोटी जांच के बाद हमने इस समाधान को बहुत अच्छे परिणामों के साथ आज़माया। TIME_WAIT अब इस ऐप के लिए कोई समस्या नहीं है।
bartosz.r

24
मैं असहमत हूं। टीसीपी के शीर्ष पर बैठे एक एप्लिकेशन स्तर प्रोटोकॉल को इस तरह से डिज़ाइन किया जाना चाहिए कि क्लाइंट हमेशा कनेक्शन को बंद कर सके। इस तरह, TIME_WAITकोई नुकसान नहीं कर ग्राहक पर बैठ जाएगा। याद रखें कि यह "UNIX नेटवर्क प्रोग्रामिंग" तीसरे संस्करण (स्टीवंस एट अल) पृष्ठ 203 में कहता है: "TIME_WAIT राज्य आपका मित्र है और हमारी मदद करने के लिए है। राज्य से बचने की कोशिश करने के बजाय, हमें इसे समझना चाहिए (धारा 2.7)। । "
एमजीडी

8
क्या होगा यदि कोई ग्राहक हर 30 सेकंड में 4000 कनेक्शन खोलना चाहता है (यह निगरानी अनुप्रयोग एक ग्राहक है! क्योंकि यह कनेक्शन शुरू करता है)? हां हम एप्लिकेशन को फिर से डिज़ाइन कर सकते हैं, बुनियादी ढांचे में कुछ स्थानीय एजेंटों को जोड़ सकते हैं, मॉडल को पुश करने के लिए बदल सकते हैं। लेकिन अगर हमारे पास पहले से ऐसा कोई आवेदन है और यह बढ़ता है, तो हम इसे ट्विंजर ट्यूनिंग करके काम कर सकते हैं। आप एक नई संरचना को लागू करने के लिए एक बजट में निवेश किए बिना, एक पैरा को बदल देते हैं, और आपके पास अचानक काम करने का आवेदन होता है।
bartosz.r

3
@ bartosz.r: मैं केवल कह रहा हूँ कि टाइमआउट 0 के साथ SO_LINGER का उपयोग करना वास्तव में एक अंतिम उपाय होना चाहिए। फिर से, "UNIX नेटवर्क प्रोग्रामिंग" तीसरे संस्करण (स्टीवंस एट अल) पृष्ठ 203 में यह भी कहा गया है कि आप डेटा भ्रष्टाचार का जोखिम उठाते हैं। RFC 1337 को पढ़ने पर विचार करें जहां आप देख सकते हैं कि TIME_WAIT आपका मित्र क्यों है।
एमजीडी

7
@caf नहीं, क्लासिक सॉल्यूशन एक कनेक्शन पूल होगा, जैसा कि हर हेवी ड्यूटी टीसीपी एपीआई में देखा जाता है, उदाहरण के लिए HTTP 1.1।
लोर्न

188

मेरे सुझाव के लिए, कृपया अंतिम खंड पढ़ें: "जब टाइमआउट 0 के साथ SO_LINGER का उपयोग किया जाए"

इससे पहले कि हम थोड़ा व्याख्यान दें:

  • सामान्य टीसीपी समाप्ति
  • TIME_WAIT
  • FIN, ACKऔरRST

सामान्य टीसीपी समाप्ति

सामान्य टीसीपी समाप्ति अनुक्रम इस तरह दिखता है (सरलीकृत):

हमारे पास दो सहकर्मी हैं: ए और बी

  1. एक कॉल close()
    • A FIN, B को भेजता है
    • A FIN_WAIT_1राज्य में जाता है
  2. B प्राप्त करता है FIN
    • B ACK, A को भेजता है
    • B CLOSE_WAITराज्य में जाता है
  3. A प्राप्त करता है ACK
    • A FIN_WAIT_2राज्य में जाता है
  4. B कॉल करता है close()
    • B FIN, A को भेजता है
    • B LAST_ACKराज्य में जाता है
  5. A प्राप्त करता है FIN
    • A ACK, B को भेजता है
    • A TIME_WAITराज्य में जाता है
  6. B प्राप्त करता है ACK
    • B CLOSEDराज्य में जाता है - अर्थात सॉकेट टेबल से हटा दिया जाता है

समय का इंतजार

तो सहकर्मी जो समाप्ति की शुरुआत करता है - यानी close()पहले कॉल करता है - TIME_WAITराज्य में समाप्त हो जाएगा ।

यह समझने के लिए कि TIME_WAITराज्य हमारा मित्र क्यों है , कृपया स्टीवंस एट अल (पृष्ठ 43) द्वारा "UNIX नेटवर्क प्रोग्रामिंग" तीसरे संस्करण में खंड 2.7 पढ़ें।

हालांकि, यह TIME_WAITएक सर्वर पर राज्य में बहुत सारे सॉकेट्स के साथ एक समस्या हो सकती है क्योंकि यह अंततः नए कनेक्शनों को स्वीकार करने से रोक सकता है।

इस समस्या के आसपास काम करने के लिए, मैंने कॉल करने से पहले टाइमआउट 0 के साथ SO_LINGER सॉकेट विकल्प सेट करने के लिए कई सुझाव दिए close()। हालाँकि, यह एक बुरा समाधान है क्योंकि यह एक त्रुटि के साथ टीसीपी कनेक्शन को समाप्त करने का कारण बनता है।

इसके बजाय, अपने एप्लिकेशन प्रोटोकॉल को डिज़ाइन करें ताकि कनेक्शन समाप्ति हमेशा क्लाइंट की ओर से शुरू की जाए। यदि क्लाइंट को हमेशा पता रहता है कि उसने सभी शेष डेटा पढ़ लिए हैं तो वह समाप्ति क्रम शुरू कर सकता है। एक उदाहरण के रूप में, एक ब्राउज़र Content-LengthHTTP हेडर से जानता है जब उसने सभी डेटा पढ़ा है और करीब शुरू कर सकता है। (मुझे पता है कि 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लंबित डेटा को छोड़ने के लिए मिला, तो पोर्ट को ठीक से रीसेट करेगा ।

मैं इस लंबे लेख की सिफारिश करूंगा जो मेरा मानना ​​है कि आपके प्रश्न का बहुत अच्छा उत्तर देता है।


6
TIME_WAITएक दोस्त ही है जब यह समस्या पैदा करने के लिए शुरू नहीं करता है: stackoverflow.com/questions/1803566/…
Pacerier

2
तो क्या होगा अगर आप एक वेब सर्वर लिख रहे हैं? आप "ग्राहक को एक करीबी पहल करने के लिए कैसे कहते हैं"?
शॉन नील

2
@ShaunNeal आप स्पष्ट रूप से नहीं। लेकिन एक अच्छी तरह से लिखा क्लाइंट / ब्राउज़र बंद करने की पहल करेगा। यदि ग्राहक अच्छी तरह से व्यवहार नहीं कर रहा है, तो सौभाग्य से हमारे पास TIME_WAIT हत्या है यह सुनिश्चित करने के लिए कि हम सॉकेट डिस्क्रिप्टर और अल्पकालिक बंदरगाहों से बाहर नहीं चलते हैं।
एमजीडी

16

जब लैंगर चालू होता है, लेकिन टाइमआउट शून्य होता है तो टीसीपी स्टैक कनेक्शन बंद करने से पहले लंबित डेटा भेजे जाने की प्रतीक्षा नहीं करता है। इसके कारण डेटा खो सकता है लेकिन इस तरह से सेटिंग करके आप इसे स्वीकार कर रहे हैं और पूछ रहे हैं कि कनेक्शन को बंद करने के बजाए सीधे बंद कर दिया जाए। इसके कारण सामान्य फिन के बजाय एक RST भेजा जाता है।

EJP को उसकी टिप्पणी के लिए धन्यवाद, विवरण के लिए यहां देखें।


1
मुझे यह समझ आ गया। जब मैं पूछ रहा हूँ "यथार्थवादी" उदाहरण के लिए जब हम हार्ड रीसेट का उपयोग करना चाहते हैं।
दिम्बा

5
जब भी आप एक कनेक्शन को खत्म करना चाहते हैं; इसलिए यदि आपका प्रोटोकॉल सत्यापन विफल हो जाता है और आपके पास एक क्लाइंट है जो आप सभी से अचानक बात कर रहा है, तो आप एक आरएसटी, आदि के साथ कनेक्शन को रद्द कर देंगे
लेन होलगेट

5
आप एक शून्य लिंगर टाइमआउट को लंजिंग के साथ भ्रमित कर रहे हैं। घंटी बंद का मतलब है कि करीब () ब्लॉक नहीं करता है। एक सकारात्मक टाइमआउट के साथ जीवन का मतलब है कि टाइमआउट तक बंद () ब्लॉक। शून्य टाइमआउट के साथ लिंग आरएसटी का कारण बनता है, और यही सवाल है।
लोर्न

2
हां, आप सही हैं। मैं अपनी शब्दावली को सही करने के लिए उत्तर को समायोजित करूँगा।
लेन होलगेट

6

आप अपने कोड में सुरक्षित रूप से लिंग को निकाल सकते हैं या नहीं यह आपके आवेदन के प्रकार पर निर्भर करता है: क्या यह एक “क्लाइंट है (टीसीपी कनेक्शन खोलना और इसे सक्रिय रूप से पहले बंद करना) या क्या यह एक“ सर्वर है ”(टीसीपी खोलने के लिए और सुन रहा है) दूसरी तरफ से बंद करने के बाद इसे बंद करना)?

यदि आपके एप्लिकेशन में “क्लाइंट” (पहले बंद) का स्वाद है और आप विभिन्न सर्वरों के लिए भारी संख्या में कनेक्शन आरंभ और बंद करते हैं (उदाहरण के लिए जब आपका ऐप एक मॉनिटरिंग ऐप है जो बड़ी संख्या में विभिन्न सर्वरों की पहुंच की निगरानी कर रहा है) तो आपका ऐप समस्या यह है कि आपके सभी क्लाइंट कनेक्शन TIME_WAIT स्थिति में अटके हुए हैं। फिर, मैं समय-समय पर डिफ़ॉल्ट रूप से छोटे मूल्य के लिए मध्यांतर को छोटा करने की सिफारिश करूंगा, लेकिन अभी भी ग्राहक कनेक्शन संसाधनों को पहले ही बंद कर दिया है। मैं 0 को टाइमआउट सेट नहीं करूंगा, क्योंकि 0 एफसी के साथ इनायत से बंद नहीं करता है लेकिन आरएसटी के साथ गर्भपात करता है।

यदि आपके एप्लिकेशन में “क्लाइंट का स्वाद है" और उसी सर्वर से बड़ी मात्रा में छोटी फ़ाइलों को प्राप्त करना है, तो आपको प्रति फ़ाइल एक नया टीसीपी कनेक्शन शुरू नहीं करना चाहिए और TIME_WAIT में क्लाइंट कनेक्शन की एक बड़ी मात्रा में समाप्त होना चाहिए, लेकिन कनेक्शन खुला रखें और एक ही कनेक्शन पर सभी डेटा प्राप्त करें। लिंग विकल्प और हटाया जा सकता है।

यदि आपका एप्लिकेशन “सर्वर है (सहकर्मी के करीबी की प्रतिक्रिया के रूप में दूसरा), तो बंद होने पर () आपका कनेक्शन शालीनतापूर्वक बंद हो जाता है और आपके द्वारा TIME_WAIT स्थिति दर्ज नहीं करने पर संसाधनों को मुक्त कर दिया जाता है। अदरक का प्रयोग नहीं करना चाहिए। लेकिन अगर आपके गंभीर ऐप में लंबे समय के लिए निष्क्रिय निष्क्रिय कनेक्शनों का पता लगाने वाली एक पर्यवेक्षी प्रक्रिया है (“लंबे समय तक परिभाषित किया जाना है) तो आप इस निष्क्रिय कनेक्शन को अपनी तरफ से बंद कर सकते हैं - इसे एक प्रकार की त्रुटि से निपटने के रूप में देखें - एक अपमानजनक संशोधन के साथ। यह linger मध्यांतर को 0. के करीब सेट करके किया जाता है (तब) ग्राहक को एक RST भेजेगा, उसे बताएगा कि आप नाराज हैं :-)


1

सर्वर में, आप ग्राहकों को दुर्व्यवहार RSTकरने के बजाय भेजना पसंद कर सकते FINहैं। स्किप के उस FIN-WAITके बाद TIME-WAITसर्वर में सॉकेट राज्यों, सर्वर संसाधन घट, और, इसलिए करने से रोकता है, डिनायल ऑफ़ सर्विस हमला इस तरह से बचाता है।


0

मुझे मैक्सिम का अवलोकन पसंद है कि डॉस हमले सर्वर संसाधनों को समाप्त कर सकते हैं। यह वास्तव में दुर्भावनापूर्ण विरोधी के बिना भी होता है।

कुछ सर्वरों को 'अनजाने डीओएस हमले' से निपटना पड़ता है जो तब होता है जब क्लाइंट ऐप में कनेक्शन लीक के साथ एक बग होता है, जहां वे आपके सर्वर पर भेजे जाने वाले प्रत्येक नए कमांड के लिए एक नया कनेक्शन बनाते रहते हैं। और फिर शायद अंततः अपने कनेक्शन को बंद कर देते हैं यदि वे जीसी दबाव से टकराते हैं, या शायद कनेक्शन अंततः समय से बाहर हो जाते हैं।

एक अन्य परिदृश्य तब होता है जब 'सभी ग्राहकों के पास समान टीसीपी पता' परिदृश्य होता है। तब क्लाइंट कनेक्शन केवल पोर्ट नंबर (यदि वे किसी एकल सर्वर से कनेक्ट होते हैं) द्वारा अलग-अलग होते हैं। और अगर ग्राहक किसी भी कारण से तेजी से साइकल चलाना / बंद करना शुरू कर देते हैं तो वे क्लाइंट (क्लाइंट एड्र + पोर्ट, सर्वर आईपी + पोर्ट) टपल-स्पेस को समाप्त कर सकते हैं।

इसलिए मुझे लगता है कि TIME_WAIT स्थिति में उच्च संख्या में सॉकेट देखने पर सर्वरों को Linger-Zero रणनीति पर स्विच करने की सलाह दी जा सकती है - हालांकि यह क्लाइंट व्यवहार को ठीक नहीं करता है, लेकिन यह प्रभाव को कम कर सकता है।


0

सर्वर पर सुनने वाला सॉकेट 0 से समय के साथ लैंगर का उपयोग कर सकता है ताकि सॉकेट से तुरंत वापस आ सके और किसी भी क्लाइंट को रीसेट कर सके जिनके कनेक्शन अभी तक कनेक्ट नहीं हुए हैं। TIME_WAIT एक ऐसी चीज़ है जो केवल तब ही दिलचस्प होती है जब आपके पास एक मल्टी-पाथ नेटवर्क होता है और मिस-ऑर्डर किए गए पैकेट के साथ समाप्त हो सकता है या अन्यथा विषम नेटवर्क पैकेट ऑर्डरिंग / आगमन-समय के साथ काम कर रहा होता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.