मैं CLOSE_WAIT सॉकेट कनेक्शन कैसे निकालूं


91

मैंने एक छोटा प्रोग्राम लिखा है जो एक विशिष्ट पोर्ट पर सर्वर के साथ इंटरैक्ट करता है। कार्यक्रम ठीक काम करता है, लेकिन:

एक बार कार्यक्रम अप्रत्याशित रूप से समाप्त हो गया, और जब से उस सॉकेट कनेक्शन को CLOSE_WAITराज्य में दिखाया गया है। अगर मैं एक प्रोग्राम चलाने की कोशिश करता हूं तो यह लटक जाता है और मुझे इसे बंद करने के लिए मजबूर करना पड़ता है, जिससे सॉकेट कनेक्शन और भी अधिक जमा होता है CLOSE_WAIT

क्या इन कनेक्शनों को फ्लश करने का कोई तरीका है?


4
आप (और नहीं करना चाहिए) कर सकते हैं। CLOSE_WAIT टीसीपी द्वारा परिभाषित एक ऐसा राज्य है, जो इस बात को स्वीकार करने के लिए समकक्ष के इंतजार में बंद है।
वॉनब्रांड

1
यह भी देखें unix.stackexchange.com/questions/10106/… ... जिसे मैं डुप्लिकेट के रूप में वोट नहीं दूंगा, क्योंकि यह प्रश्न को ऑफ-टॉपिक के रूप में बंद कर देगा।
derobert

4
@vonbrand नहीं यह नहीं है, यह बिल्कुल विपरीत है। यह एक कनेक्शन के लिए राज्य है जो पहले से ही सहकर्मी द्वारा बंद कर दिया गया है और इसके अंत को बंद करने के लिए स्थानीय आवेदन की प्रतीक्षा कर रहा है।
लोरेन के मार्कीस

यदि आप Commons HttpClient का उपयोग कर रहे हैं तो nuxeo.com/blog/… के पास बहुत सारी प्रासंगिक जानकारी है। RFC 2616 से, धारा 14: HTTP / 1.1 अनुप्रयोग जो लगातार कनेक्शन का समर्थन नहीं करते हैं, उन्हें हर संदेश में "करीब" कनेक्शन विकल्प शामिल करना चाहिए।
मयंक आहूजा

जवाबों:


79

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

SO_REUSEADDRसर्वर और TIME_WAITसॉकेट के लिए है, इसलिए यहां लागू नहीं होता है।


2
अच्छी तरह से ... प्रक्रिया को मारना सबसे अच्छा नहीं हो सकता है यदि वह प्रोग्राम बहुत अधिक कनेक्शन खोलता है, केवल "CLOSE_WAIT" में रहने वालों में से कुछ: उस मामले में प्रक्रिया को मारना पूरी तरह से असंभव या अनुचित हो सकता है (प्रोग्राम अभी भी काम करता है) सेवाएं प्रदान करता है, उन अन्य कनेक्शनों के साथ)। बस लंबित कनेक्शन को बंद करना अधिक उचित होगा। लेकिन वास्तव में यह आम तौर पर प्रोग्राम ही होता है जो कि स्थानीय रूप से कनेक्टिनो (CLOSE_WAIT) को बंद नहीं कर रहा है, इसका मतलब है कि इसे दूसरे छोर से 'फिन' प्राप्त हुआ है और प्रोग्राम को स्थानीय रूप से कनेक्शन बंद करना है)। एक बग रिपोर्ट उपयुक्त हो सकती है
ओलिवियर दुलक

41

जैसा कि क्रिस्ट क्लार्क ने बताया है ।

CLOSE_WAIT का अर्थ है कि कनेक्शन के स्थानीय छोर को दूसरे छोर से एक फिन प्राप्त हुआ है, लेकिन ओएस वास्तव में अपने कनेक्शन को बंद करने के लिए स्थानीय छोर पर कार्यक्रम की प्रतीक्षा कर रहा है।

समस्या यह है कि आपका प्रोग्राम स्थानीय मशीन पर चल रहा है और सॉकेट बंद नहीं कर रहा है। यह एक टीसीपी ट्यूनिंग मुद्दा नहीं है। एक कनेक्शन (और काफी सही ढंग से) CLOSE_WAIT में हमेशा के लिए रह सकता है जबकि प्रोग्राम कनेक्शन खुला रखता है।

एक बार जब स्थानीय प्रोग्राम सॉकेट बंद कर देता है, तो OS फ़ाइनल को दूरस्थ छोर पर भेज सकता है, जो फ़िन के ACK की प्रतीक्षा करते समय आपको LAST_ACK में स्थानांतरित करता है। एक बार जब यह प्राप्त हो जाता है, तो कनेक्शन समाप्त हो जाता है और कनेक्शन तालिका से गिर जाता है (यदि आपका अंत CLOSE_WAIT में है तो आप TIME_WAIT स्थिति में समाप्त नहीं होते हैं)।


4
सॉकेट कैसे बंद करें ??
दिव्यांग शाह

1
आपने अपने द्वारा खोले गए सॉकेट के हैंडल को बंद कर दिया है। का प्रयोग करें close()या closesocket()है, जो मंच आप उपयोग कर रहे हैं पर निर्भर करता।
रेमी लेबेउ

8

मैं भी एक बहुत ही नवीनतम Tomcat सर्वर (7.0.40) के साथ एक ही मुद्दा रहा हूँ। यह एक-दो दिनों के लिए गैर-उत्तरदायी हो जाता है।

खुले कनेक्शन देखने के लिए, आप उपयोग कर सकते हैं:

sudo netstat -tonp | grep jsvc | grep --regexp="127.0.0.1:443" --regexp="127.0.0.1:80" | grep CLOSE_WAIT

जैसा कि इस पोस्ट में बताया गया है , आप /proc/sys/net/ipv4/tcp_keepalive_timeमूल्यों को देखने के लिए उपयोग कर सकते हैं । मान सेकंड और डिफॉल्ट में 7200 (2 घंटे) पर लगता है।

उन्हें बदलने के लिए, आपको संपादित करने की आवश्यकता है /etc/sysctl.conf

Open/create `/etc/sysctl.conf`
Add `net.ipv4.tcp_keepalive_time = 120` and save the file
Invoke `sysctl -p /etc/sysctl.conf`
Verify using `cat /proc/sys/net/ipv4/tcp_keepalive_time`

4
जवाब भ्रामक है। आपने कहा कि गैर-उत्तरदायी राज्य कई दिनों के लिए चले गए हैं .. लेकिन फिर आप भी केवल 120 सेकंड तक जीवित समय निर्धारित करने का प्रयास करते हैं। डिफ़ॉल्ट मान (7200 सेकंड) के साथ भी, यह कई दिनों तक नहीं चलना चाहिए, है ना?
फेनचैना

8

भले ही बहुत अधिक CLOSE_WAIT कनेक्शन का अर्थ है कि पहले आपके कोड में कुछ गड़बड़ है और यह अच्छा अभ्यास नहीं है।

आप बाहर की जाँच कर सकते हैं: https://github.com/rghose/kill-close-wait-connections

यह स्क्रिप्ट क्या करती है ACK को भेजें जो कनेक्शन के लिए इंतजार कर रहा था।

इसी से मेरा काम बना है।


आप एक्ट को क्लोज-वेट सॉकेट में भेजते हैं। के साथ काम नहीं करता है .. अगर काम करता है, क्यों?
चिनक्सिंग

मैं अनुमान लगा रहा हूं, ओएस ने पहले ही रिमोट होस्ट को फिन भेज दिया है। दूरस्थ होस्ट शायद ACK के साथ उत्तर नहीं दे सकता है जो सॉकेट की अपेक्षा कर रहा है।
मृगतृष्णा

हाँ, यह सही है (कर्नेल कोड से)। लेकिन मुझे आपके द्वारा भेजे गए पैकेट के SEQ के बारे में भी संदेह है, जो "10" है, क्या कर्नेल इसकी जांच नहीं करता है?
चिनक्सिंग

शायद ऩही। मुझे लगता है कि मैंने कई यादृच्छिक संख्याओं के साथ कोशिश की, और वे काम करने लगे।
मृगतृष्णा

3

यह उल्लेख किया जाना चाहिए कि Socketक्लाइंट और सर्वर एंड दोनों में उदाहरण स्पष्ट रूप से लागू करने की आवश्यकता है close()। यदि सिर्फ़ सिरों में से कोई एक आह्वान करता close()है, तो भी, सॉकेट CLOSE_WAIT स्थिति में रहेगा।


3

आप ssकमांड के साथ जबरन बंद कर सकते हैं ; ssआदेश netstat को सॉकेट सांख्यिकी और जानकारी प्रदर्शित करता है इसी तरह से (सरल हालांकि और तेजी से) डंप करने के लिए इस्तेमाल एक उपकरण है।

CLOSE_WAIT स्थिति में किसी भी सॉकेट को मारने के लिए, इसे चलाएं (रूट के रूप में)

$ ss --tcp state CLOSE-WAIT --kill

1

यह भी ध्यान देने योग्य है कि यदि आपका कार्यक्रम एक नई प्रक्रिया को जन्म देता है, तो यह प्रक्रिया आपके सभी खोले गए हैंडल को प्राप्त कर सकती है। यहां तक ​​कि अपने स्वयं के प्रोग्राम क्लॉस के बाद, उन विरासत वाले हैंडल अभी भी अनाथ बच्चे की प्रक्रिया के माध्यम से जीवित हो सकते हैं। और वे जरूरी नहीं कि netstat में बहुत समान दिखाते हैं। लेकिन सभी समान, सॉकेट CLOSE_WAIT में घूमता रहेगा जबकि यह बाल प्रक्रिया जीवित है।

मेरे पास एक मामला था जहां मैं एडीबी चला रहा था। ADB स्वयं एक सर्वर प्रक्रिया को जन्म देता है यदि उसका पहले से चल नहीं रहा है। यह शुरू में मेरे सभी हैंडल को विरासत में मिला था, लेकिन जब मैं जांच कर रहा था तो उनमें से किसी के मालिक होने के रूप में नहीं दिखा था (यह मैकओएस और विंडोज दोनों के लिए सच था - लिनक्स के बारे में निश्चित नहीं)।

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