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


113

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

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


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

जवाबों:


148
/etc/init.d/networking restart

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

यह नियंत्रण संकेतों जैसे समाप्ति अनुरोध / प्रतिक्रिया के लिए समान है। RFC 793 टाइम-वॉइट स्थिति को निम्नानुसार परिभाषित करता है:

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

निम्नलिखित टीसीपी राज्य आरेख देखें: वैकल्पिक शब्द

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

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

RFC 793 अधिकतम सेगमेंट लाइफटाइम या 2MSL होने के लिए TIME-OUT सेट करता है। MSL के बाद से, एक पैकेट अधिकतम समय इंटरनेट पर घूम सकता है, 2 मिनट के लिए सेट होता है, 2MSL 4 मिनट का होता है। चूँकि ACK में ACK नहीं है, इसलिए सक्रिय करीब कुछ भी नहीं कर सकता है, लेकिन 4 मिनट प्रतीक्षा करने के लिए अगर यह TCP / IP प्रोटोकॉल का सही ढंग से पालन करता है, बस निष्क्रिय प्रेषक ने AC को इसके अंतिम (सैद्धांतिक रूप से) प्राप्त नहीं किया है ।

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

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

/etc/init.d/networking restart

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

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


8
शानदार जवाब, लेकिन उनके सवाल का सही जवाब नहीं। नेटवर्किंग को पुनरारंभ करना काम करेगा, लेकिन फिर रिबूट करना होगा, इसलिए यह सही नहीं हो सकता है।
क्रिस हुआंग-लीवर

3
@ क्रिस हुआंग-लीवर, सवाल यह है कि "क्या कोई प्रोग्राम है जिसे आप तुरंत बलपूर्वक चला सकते हैं कि सॉकेट TIME_WAIT राज्य से बाहर चला जाए?" अगर रिबूटिंग को एक कार्यक्रम चलाने के रूप में माना जा सकता है, तो यह भी एक सही जवाब होगा। आपको क्यों लगता है कि यह सही नहीं हो सकता है?
यूजीन योकोटा

8
डब्लूएमआर का सबसे उपयोगी उत्तर है (जो कि इस तरह के मुद्दे पर चलने पर मैं क्या करता हूं)। नेटवर्क को फिर से शुरू करना समाधान के लिए बहुत कठोर है, और केवल टाइमआउट की प्रतीक्षा करने में अधिक समय लग सकता है। उसके प्रश्न का सही उत्तर 'नहीं' है, लेकिन एसओ आपको दो पत्र उत्तर टाइप करने की अनुमति नहीं देगा :-)
क्रिस हुआंग- लीवर

6
ओह ठीक है, अगली बार जब कुछ प्रक्रिया SIGTERM पर लटकेगी तो मैं इसे ठीक करने के बजाय अपने कंप्यूटर को तोड़ दूंगा।
लॉन्गपोक

इसका सामान्यीकरण "नेटवर्क सेवाओं को फिर से शुरू करना" है। विशिष्ट स्थान /etc/init.d/networkingप्लेटफ़ॉर्म-विशिष्ट (डेबियन?) है, इसलिए सटीक कमांड लाइन अन्य प्रणालियों के लिए अलग (कभी-कभी मौलिक रूप से इतनी) अलग होगी। मैं अन्य टिप्पणीकारों से सहमत हूं कि यह गंभीर overkill की तरह लगता है और स्पष्ट रूप से किसी भी असंबंधित नेटवर्क सेवाओं के लिए विघटनकारी है।
ट्रिपल जू

51

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

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


लेकिन मुझे पहले से बाध्य त्रुटि नहीं मिली। जब मैं प्रोग्राम को फिर से निष्पादित करता हूं तो यह पोस्ट (123456) में सुनता है मैं यह भी देख सकता हूं कि सिस्टम उस पोर्ट के लिए TIME_WAIT दिखा रहा है लेकिन फिर भी मैं कनेक्ट कर सकता हूं। क्यों?
जयपाल चंद्रन

2
SO_REUSEADDR के साथ भी, "अभी भी उपयोग में पहले से ही पता" त्रुटि प्राप्त करना संभव है। जानकारी के लिए, देखें-www.harvard.edu/~fine/Tech/addrinuse.html
जिंगुगो याओ

@MR SO_REUSEADDRसॉकेट को "बंद" नहीं करता है। यह केवल उन लोगों को पुन: उपयोग करने में सक्षम बनाता है जो पहले से ही खुले हैं। तो सवाल अभी भी है "जबरन एक सॉकेट को बंद कैसे करें TIME_WAIT?"
पचेरियर

यह सही उत्तर है, लेकिन सवाल पूरी तरह से सही नहीं था। कम से कम मेरी समस्या को अच्छी तरह से हल किया (पूरे नेटवर्क को फिर से शुरू करने के साथ-साथ अन्य सभी कनेक्शनों को फिर से शुरू करने की तरह नहीं)।
V-Mark

SO_REUSEADDRbind()आगे बढ़ने देंगे ; लेकिन अगर आप उस सॉकेट को सुनना चाहते हैं, तो सभी समान listen()वापस कर देंगे EADDRINUSE। दूसरे शब्दों में, यह जवाब ग्राहक सॉफ्टवेयर को अल्पकालिक बंदरगाहों का उपयोग करने में मदद कर सकता है, लेकिन सर्वर सॉफ्टवेयर के लिए समस्या को हल नहीं करता है।
विल

33

जहां तक ​​मुझे पता है कि आपके प्रोग्राम में बेहतर सिग्नल हैंडलर लिखने के बाहर सॉकेट को जबरन बंद करने का कोई तरीका नहीं है, लेकिन एक / 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 की वृद्धि। इसलिए, यदि आपके पास स्रोत कोड का नियंत्रण है, तो आप इस व्यवहार को कुछ सेकंड प्रतीक्षा करने और वेतन वृद्धि के बजाय उसी पोर्ट पर पुनः प्रयास कर सकते हैं।


लगता है कि दूसरे दो उदाहरण s / rw / tw / I को संपादित करने चाहिए, लेकिन पर्याप्त प्रतिनिधि की कमी है।

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

इसे 1भविष्य के कनेक्शन के लिए काम करने के लिए सेट करना , लेकिन उन मौजूदा लोगों के बारे में क्या है जो पहले से ही खोले गए हैं?
पचेरियर

18

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

अद्यतन: एक और समाधान कटर है जो कुछ linux distros 'रिपॉजिटरी में आता है।


3

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


2
यह किसी भी आउटबाउंड डेटा को भी खो देता है जो अभी भी पारगमन में है, और दूसरे छोर पर त्रुटि का कारण हो सकता है। सिफारिश नहीं की गई।
user207421

@ ईजेपी फेलिंग लगभग हमेशा सही कॉल है। नेटवर्किंग विश्वसनीय नहीं है, और लड़ाई जो चीजों को धीमा कर देगी। दुर्घटनाग्रस्त ऐप यह नहीं मान सकता है कि किसी भी डेटा ने इसे सुरक्षित रूप से बनाया है।
तोबू

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

@ टोबू नेटवर्किंग विश्वसनीय नहीं है, लेकिन टीसीपी होने की कोशिश करता है, और यह बदतर बनाने से कुछ भी बेहतर नहीं बनता है, और टीसीपी को अपना काम करने देना कुछ भी 'लड़ाई' का गठन नहीं करता है।
user207421

2

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

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


0

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

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