सवाल TIME_WAIT में जबरन सॉकेट को कैसे बंद करें?


मैं लिनक्स पर एक विशेष कार्यक्रम चलाता हूं जो कभी-कभी दुर्घटनाग्रस्त हो जाता है। यदि आप इसके तुरंत बाद इसे खोलते हैं, तो यह पहली बार 49200 के बजाय सॉकेट 49201 पर सुनता है। नेटस्टैट से पता चलता है कि 49200 एक TIME_WAIT राज्य में है।

क्या कोई प्रोग्राम है जिसे आप तुरंत सॉकेट को TIME_WAIT स्थिति से बाहर करने के लिए मजबूर कर सकते हैं?


109
2017-09-03 12:57


मूल


यदि आप यहां हैं "बहुत अधिक TIME_WAIT सर्वर पर "बस के माध्यम से छोड़ो पहले तीन उत्तरों जो जवाब देने के बजाय सवाल से बचते हैं। - Pacerier


जवाब:


/etc/init.d/networking restart

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

यह नियंत्रण संकेतों जैसे कि समाप्ति अनुरोध / प्रतिक्रिया के लिए समान होता है। आरएफसी 793 समय-समय पर राज्य को परिभाषित करता है:

TIME-WAIT - के लिए प्रतीक्षा का प्रतिनिधित्व करता है   सुनिश्चित करने के लिए पर्याप्त समय है       रिमोट टीसीपी को इसके कनेक्शन की स्वीकृति मिली       समाप्ति अनुरोध

निम्नलिखित टीसीपी राज्य आरेख देखें: alt text

टीसीपी एक द्विदिश संचार प्रोटोकॉल है, इसलिए जब कनेक्शन स्थापित किया जाता है, तो क्लाइंट और सर्वर के बीच कोई अंतर नहीं होता है। इसके अलावा, कोई भी छोड़ने को कॉल कर सकता है, और दोनों सहकर्मियों को एक स्थापित टीसीपी कनेक्शन को पूरी तरह बंद करने के लिए बंद होने पर सहमत होना चाहिए।

आइए पहले को कॉल को सक्रिय रूप से बंद करने के लिए कॉल करें, और दूसरा सहकर्मी निष्क्रिय हो। जब सक्रिय करीब एफआईएन भेजता है, तो राज्य फिन-वाइट -1 में जाता है। फिर इसे भेजे गए एफआईएन के लिए एक एसीके प्राप्त होता है और राज्य फिन-डब्ल्यूएआईटी -2 पर जाता है। एक बार यह निष्क्रिय निकट से भी एफआईएन प्राप्त करता है, सक्रिय करीब एसीके को एफआईएन भेजता है और राज्य TIME-WAIT पर जाता है। यदि निष्क्रिय निकट को दूसरी एफआईएन में एसीके नहीं मिला, तो यह एफआईएन पैकेट को फिर से प्रेषित कर देगा।

आरएफसी 793 टाइम-आउट को अधिकतम सेगमेंट लाइफटाइम, या 2MSL से दोगुना सेट करता है। एमएसएल के बाद से, एक पैकेट इंटरनेट के चारों ओर घूमने का अधिकतम समय, 2 मिनट तक सेट हो जाता है, 2MSL 4 मिनट है। चूंकि एसीके के लिए कोई एसीके नहीं है, इसलिए सक्रिय करीब 4 मिनट तक इंतजार नहीं कर सकता है, अगर यह टीसीपी / आईपी प्रोटोकॉल का सही पालन करता है, तो निष्क्रिय प्रेषक को अपने एफआईएन (सैद्धांतिक रूप से) को एसीके नहीं मिला है। ।

हकीकत में, लापता पैकेट शायद दुर्लभ हैं, और बहुत दुर्लभ हैं यदि यह सब लैन के भीतर या एक मशीन के भीतर हो रहा है।

सवाल verbatim, कैसे करें जवाब देने के लिए बलपूर्वक TIME_WAIT में सॉकेट बंद करें, मैं अभी भी अपने मूल उत्तर से चिपके रहूंगा:

/etc/init.d/networking restart

व्यावहारिक रूप से बोलते हुए, मैं इसे प्रोग्राम करूंगा ताकि यह डब्लूएमआर के रूप में SO_REUSEADDR विकल्प का उपयोग करके TIME-WAIT स्थिति को अनदेखा कर सके। SO_REUSEADDR वास्तव में क्या करता है?

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


139
2017-09-03 13:11



महान जवाब, लेकिन उनके प्रश्न का सही जवाब नहीं है। नेटवर्किंग को पुनरारंभ करना काम करेगा, लेकिन फिर रीबूट हो जाएगा, इसलिए यह सही नहीं हो सकता है। - Chris Huang-Leaver
@ क्रिस हुंग-लीवर, सवाल यह है कि "क्या कोई ऐसा कार्यक्रम है जिसे आप तुरंत सॉकेट को TIME_WAIT स्थिति से बाहर करने के लिए मजबूर कर सकते हैं?" यदि रीबूटिंग को प्रोग्राम चलाने पर विचार किया जा सकता है, तो यह भी एक सही जवाब होगा। आपको ऐसा क्यों लगता है कि यह सही नहीं हो सकता है? - Eugene Yokota
डब्लूएमआर का सबसे उपयोगी उत्तर है (जब मैं इस तरह के मुद्दे पर चलता हूं तो मैं यही करता हूं)। नेटवर्क को पुनरारंभ करना समाधान के लिए बहुत कठोर है, और समय-समय पर प्रतीक्षा करने से अधिक समय ले सकता है। उनके प्रश्न का सही उत्तर 'नहीं' है, लेकिन SO आपको दो अक्षर उत्तर टाइप करने नहीं देगा :-) - Chris Huang-Leaver
ओह ठीक है, अगली बार कुछ प्रक्रिया SIGTERM पर लटकती है मैं इसे ठीक करने के बजाय अपने कंप्यूटर को तोड़ दूंगा। - Longpoke


मुझे नहीं पता कि आपके पास उस विशेष प्रोग्राम का स्रोत कोड है जो आप चल रहे हैं, लेकिन यदि ऐसा है तो आप केवल SO_REUSEADDR को सेट कर सकते हैं setsockopt(2) जो आपको सॉकेट को TIME_WAIT स्थिति में होने पर भी उसी स्थानीय पते पर बाध्य करने की अनुमति देता है (जब तक कि सॉकेट सक्रिय रूप से सुन नहीं रहा हो, देखें socket(7))।

TIME_WAIT स्थिति के बारे में अधिक जानकारी के लिए देखें यूनिक्स सॉकेट अकसर किये गए सवाल


50
2017-09-03 13:17



लेकिन मुझे पहले से ही बाध्य त्रुटि नहीं मिली। जब मैं प्रोग्राम को फिर से निष्पादित करता हूं तो यह पोस्ट (123456) में सुनता है, मैं यह भी देख सकता हूं कि सिस्टम उस बंदरगाह के लिए TIME_WAIT दिखा रहा है लेकिन फिर भी मैं कनेक्ट कर सकता हूं। क्यूं कर? - Jayapal Chandran
SO_REUSEADDR के साथ भी, "पता पहले से उपयोग में" त्रुटि प्राप्त करना अभी भी संभव है। विवरण के लिए, देखें hea-www.harvard.edu/~fine/Tech/addrinuse.html। - Jingguo Yao
@WMR SO_REUSEADDR एक सॉकेट "बंद" नहीं करता है। यह केवल उन लोगों का पुन: उपयोग करने में सक्षम बनाता है जो पहले ही खोले गए हैं। तो सवाल अभी भी है "कैसे एक सॉकेट जबरन बंद करने के लिए TIME_WAIT? " - Pacerier


जहां तक ​​मुझे पता है कि सॉकेट को अपने कार्यक्रम में एक बेहतर सिग्नल हैंडलर लिखने के बाहर जबरन बंद करने का कोई तरीका नहीं है, लेकिन एक / proc फ़ाइल है जो नियंत्रित करता है कि कितना समय लगता है। फाइल है

/proc/sys/net/ipv4/tcp_tw_recycle

और आप इसे कर कर टाइमआउट को 1 सेकंड पर सेट कर सकते हैं:

echo 1 > /proc/sys/net/ipv4/tcp_tw_recycle 

हालाँकि, यह पन्ना इस चर को सेट करते समय संभावित विश्वसनीयता समस्याओं के बारे में एक चेतावनी शामिल है।

एक संबंधित फाइल भी है

/proc/sys/net/ipv4/tcp_tw_reuse

जो नियंत्रित करता है कि TIME_WAIT सॉकेट का पुन: उपयोग किया जा सकता है (संभावित रूप से बिना किसी टाइमआउट के)।

संयोग से, कर्नेल प्रलेखन आपको तकनीकी विशेषज्ञों की सलाह / अनुरोध के बिना इन मूल्यों में से किसी एक को बदलने के लिए चेतावनी देता है। जो मैं नहीं हूँ

यह कार्यक्रम बंदरगाह 49200 के लिए बाध्यकारी प्रयास करने के लिए लिखा गया था और फिर बंदरगाह पहले से उपयोग में आने पर 1 से बढ़ता है। इसलिए, यदि आपके पास स्रोत कोड का नियंत्रण है, तो आप कुछ सेकंड प्रतीक्षा करने के लिए इस व्यवहार को बदल सकते हैं और बढ़ते रहने के बजाय उसी पोर्ट पर पुनः प्रयास कर सकते हैं।


32
2017-09-03 13:24



लगता है कि दूसरे दो उदाहरण एस / आरडब्ल्यू / tw / मैं संपादित करना होगा, लेकिन पर्याप्त प्रतिनिधि की कमी है।
कर्नेल दस्तावेज से लिया गया: सावधानी। Tcp_tw_recycle और tcp_tw_reuse दोनों समस्याएं पैदा कर सकते हैं। आपको नोड (ओं) के बीच नेटवर्क टोपोलॉजी को समझने के बिना या तो पैरामीटर सक्षम होने पर नोड द्वारा उपयोग या उपयोग करने में सक्षम नहीं होना चाहिए। कनेक्शन जो नोड्स के माध्यम से जाते हैं जो टीसीपी कनेक्शन राज्यों से अवगत हैं, जैसे फ़ायरवॉल, एनएटी या लोड बैलेंसर सेटिंग के कारण फ्रेम छोड़ना शुरू कर सकते हैं। पर्याप्त संख्या में कनेक्शन होने पर समस्या दिखाई देगी।
इसे स्थापित करना 1 भविष्य के कनेक्शन के लिए काम करता है, लेकिन उन मौजूदा लोगों के बारे में क्या जो पहले ही खोले गए हैं? - Pacerier


वास्तव में एक कनेक्शन को मारने का एक तरीका है - killcx। वे दावा करते हैं कि यह कनेक्शन के किसी भी राज्य में काम करता है (जिसे मैंने सत्यापित नहीं किया है)। आपको इंटरफ़ेस को जानने की आवश्यकता है जहां संचार होता है, ऐसा लगता है कि यह डिफ़ॉल्ट रूप से eth0 मानता है।

अद्यतन: एक और समाधान है काटने वाला जो कुछ लिनक्स distros 'भंडार में आता है।


16
2017-10-30 17:32



धन्यवाद! यह उपयोगिता बहुत अच्छा काम करता है! मुझे एक लंबी नौकरी फिर से शुरू करने से बचाया। - Zanson


एक और विकल्प SO_LINGER विकल्प का उपयोग 0 के टाइमआउट के साथ करना है। इस तरह, जब आप सॉकेट को बंद करते हैं तो जबरन बंद कर दिया जाता है, तो एफआईएन / एसीके समापन व्यवहार में जाने के बजाय आरएसटी भेजना। यह TIME_WAIT स्थिति से बच जाएगा, और कुछ उपयोगों के लिए अधिक उपयुक्त हो सकता है।


3
2018-06-10 22:33



यह किसी भी आउटबाउंड डेटा को भी खो देता है जो अभी भी पारगमन में है, और दूसरी तरफ एक त्रुटि हो सकती है। सिफारिश नहीं की गई। - user207421
@EJP जल्दी विफल होना लगभग हमेशा सही कॉल है। नेटवर्किंग विश्वसनीय नहीं है, और लड़ाई जो चीजों को धीमा कर देगी। एक क्रैश ऐप यह नहीं मान सकता कि किसी भी डेटा ने इसे सुरक्षित रूप से बनाया है। - Tobu
दरअसल, मैं किसी भी दिन इसकी सिफारिश करता हूं जब दूसरा एंडपॉइंट एक छोटी गाड़ी, एम्बेडेड औद्योगिक बस गेटवे है जो टीसीपी पर अपने स्वयं के एप्लिकेशन-लेयर विश्वसनीय परिवहन को लागू करता है, जहां कहा गया है कि परिवहन कभी भी बंद होने से रोकता है जब तक कि वह आरएसटी प्राप्त नहीं करता और इस प्रकार भर जाता है उस गेटवे पर कनेक्शन सीमा। क्या आप वहां मौजूद हैं। मैंने आपको एक बहुत ही विशिष्ट और बहुत वास्तविक उदाहरण दिया है, दुख की बात है, इस तरह हैक का सहारा लेना आवश्यक है। - andyn
@ टोबू नेटवर्किंग विश्वसनीय नहीं है, लेकिन टीसीपी बनने की कोशिश करता है, और इससे भी बदतर बनाने से कुछ भी बेहतर नहीं होता है, और टीसीपी को अपना काम करने देना कुछ भी 'लड़ाई' नहीं बनता है। - user207421


एक वैकल्पिक समाधान कुछ विश्वसनीय प्रॉक्सी या पोर्ट फॉरवर्डिंग सॉफ़्टवेयर होगा जो पोर्ट 49200 पर सुनता है, फिर अलग-अलग बंदरगाहों का उपयोग करके अपने कम विश्वसनीय कार्यक्रम के कई उदाहरणों में कनेक्शन को आगे बढ़ाएं ... हैप्रोक्सी स्प्रिंग्स को दिमाग में रखें।

संयोग से आपके कनेक्टिंग पोर्ट बहुत अधिक है। आप 0-1024 रेंज के ऊपर एक अप्रयुक्त एक का उपयोग करने का प्रयास कर सकते हैं। आपके सिस्टम को एक निचला बंदरगाह संख्या का उपयोग एक अल्पकालिक बंदरगाह के रूप में करने की संभावना कम है।


2
2017-08-21 20:28





सॉकेट प्रोग्रामिंग क्लाइंट सर्वर आर्किटेक्चर में TIME_WAIT सबसे आम समस्या है। आवधिक रूप से प्रयास करने के लिए कुछ सेकंड प्रतीक्षा करें इसके लिए सबसे अच्छा समाधान है। वास्तविक समय अनुप्रयोगों के लिए उन्हें सर्वर को तुरंत उठना होगा उनके लिए SO_REUSEADDR विकल्प है।


0
2017-10-13 19:07