2013-02-08 32 views
6

मैं एक सी आधारित लिनक्स सॉकेट प्रोग्राम डीबग कर रहा हूं।लिनक्स सॉकेट: क्लाइंट प्रोग्राम में डिस्कनेक्ट किए गए नेटवर्क का पता कैसे लगाएं?

sockfd= socket(AF_INET, SOCK_STREAM, 0); 

connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)); 

send_bytes = send(sockfd, sock_buff, (size_t)buff_bytes, MSG_DONTWAIT); 

मैं जब निकालने सर्वर अपने सर्वर कार्यक्रम बंद कर देता है वियोग का पता लगाने कर सकते हैं: सभी उदाहरणों वेबसाइटों में उपलब्ध के रूप में, मैं निम्नलिखित संरचना लागू होता है। लेकिन अगर मैं ईथरनेट केबल को अनप्लग करता हूं, तो प्रेषण फ़ंक्शन अभी भी -1 के बजाय सकारात्मक मान लौटाता है।

मैं क्लाइंट प्रोग्राम में नेटवर्क कनेक्शन कैसे देख सकता हूं यह मानते हुए कि मैं सर्वर की तरफ नहीं बदल सकता?

उत्तर

28

लेकिन अगर मैं ईथरनेट केबल को अनप्लग करता हूं, तो प्रेषण फ़ंक्शन अभी भी के बजाय सकारात्मक मान लौटाता है।

सबसे पहले आपको पता होना चाहिए कि send वास्तव में कुछ भी नहीं भेजता है, यह सिर्फ एक स्मृति-प्रतिलिपि कार्य/सिस्टम कॉल है। यह आपकी प्रक्रिया से डेटा को कर्नेल में कॉपी करता है - कुछ समय बाद कर्नेल उस डेटा को लाएगा और इसे सेगमेंट और पैकेट में पैकेजिंग के बाद दूसरी तरफ भेज देगा। इसलिए send ही अगर एक त्रुटि लौट सकते हैं:

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

मुख्य मुद्दा यह है कि send कुछ भी नहीं भेजता है और इसलिए अपनी वापसी कोड आपको बता नहीं करता है कॉपी करने के लिए नहीं है कुछ भी डेटा वास्तव में दूसरी तरफ तक पहुंचने के बारे में।

आपके प्रश्न पर वापस, जब टीसीपी डेटा भेजता है तो यह उचित समय में वैध स्वीकृति की अपेक्षा करता है। अगर यह एक नहीं मिलता है, तो यह रहता है। यह कितनी बार फिर से रहता है? प्रत्येक टीसीपी स्टैक चीजों को अलग करता है, लेकिन मानक घातीय बैकऑफ का उपयोग करना है। यही है, पहले 1 सेकंड प्रतीक्षा करें, फिर 2, फिर 4 और इसी तरह। कुछ ढेर पर इस प्रक्रिया में कुछ मिनट लग सकते हैं।

मुख्य बिंदु यह है कि एक बाधा के मामले में टीसीपी गंभीर रूप से बड़ी अवधि की मौन (लिनक्स पर 15 रीट्रीज़ की तरह कुछ करता है - 5 मिनट से अधिक) के बाद एक कनेक्शन मृत घोषित करेगा।

इसे हल करने का एक तरीका है अपने आवेदन में कुछ पावती तंत्र को लागू करना। उदाहरण के लिए आप 5 सेकंड के भीतर सर्वर "उत्तर" के लिए अनुरोध भेज सकते हैं या मैं इस कनेक्शन को मृत समय "और फिर recv को टाइमआउट के साथ घोषित कर दूंगा।

1

एक रिमोट डिस्कनेक्ट का पता लगाने, अधिक जानकारी के लिए एक read()

चेक इस सूत्र करने के लिए:

Can read() function on a connected socket return zero bytes?

+0

प्रश्न ईथरनेट केबल को अनप्लग करने के बारे में है। – EJP

1

चेक वापसी मान, और देखें कि क्या वह इस मूल्य के बराबर है:

ईपीआईपीई
यह सॉकेट जुड़ा हुआ था लेकिन कनेक्शन अब टूटा हुआ है। इस मामले में, भेजें पहले एक सिगिप सिग्नल उत्पन्न करता है; अगर उस सिग्नल को अनदेखा या अवरुद्ध किया गया है, या यदि उसके हैंडलर लौटते हैं, तो ईपीआईपीई के साथ भेजता है।

इसके अलावा अपने हैंडलर में सिगिप सिग्नल के लिए एक चेक भी जोड़ें, ताकि इसे और अधिक नियंत्रित किया जा सके।

0

आप केवल लिखने() funcation को कॉल करने के साथ अनप्लग ईथरनेट केबल का पता नहीं लगा सकते हैं। यह आपकी चेतना के बिना टीसीपी स्टैक द्वारा किए गए टीसीपी रीट्रांसमिशन की वजह से है। यहां समाधान हैं।

भले ही आप पहले से ही अपने एप्लिकेशन सॉकेट में रखरखाव विकल्प सेट करते हैं, फिर भी आप अपने सॉकेट पर सॉकेट लिखते समय सॉकेट की मृत कनेक्शन स्थिति का पता नहीं लगा सकते हैं। यह कर्नेल टीसीपी स्टैक द्वारा टीसीपी रीट्रान्समिशन की वजह से है। tcp_retries1 और tcp_retries2 tcp retransmission टाइमआउट को कॉन्फ़िगर करने के लिए कर्नेल पैरामीटर हैं। रीट्रान्समिशन टाइमआउट के सटीक समय की भविष्यवाणी करना मुश्किल है क्योंकि इसकी गणना आरटीटी तंत्र द्वारा की जाती है। आप आरएफसी 7 9 3 में इस गणना को देख सकते हैं। (3.7। डाटा कम्युनिकेशन)

https://www.rfc-editor.org/rfc/rfc793.txt

प्रत्येक प्लेटफार्मों टीसीपी पुनर्संचरण के लिए कर्नेल विन्यास है।

Linux : tcp_retries1, tcp_retries2 : (exist in /proc/sys/net/ipv4) 

http://linux.die.net/man/7/tcp

HPUX : tcp_ip_notify_interval, tcp_ip_abort_interval 

http://www.hpuxtips.es/?q=node/53

AIX : rto_low, rto_high, rto_length, rto_limit 

http://www-903.ibm.com/kr/event/download/200804_324_swma/socket.pdf

आप tcp_retries2 (डिफ़ॉल्ट 15) यदि आप जल्दी मृत कनेक्शन का पता लगाने के लिए चाहते हैं के लिए कम मूल्य निर्धारित करना चाहिए, लेकिन यह है मैं पहले से ही सटीक समय नहीं है कहा हुआ। इसके अतिरिक्त, वर्तमान में आप केवल उन सॉकेट को एकल सॉकेट के लिए सेट नहीं कर सकते हैं। वे वैश्विक कर्नेल पैरामीटर हैं। एकल सॉकेट (http://patchwork.ozlabs.org/patch/55236/) के लिए टीसीपी रीट्रांसमिशन सॉकेट विकल्प लागू करने के लिए कुछ परीक्षण किया गया था, लेकिन मुझे नहीं लगता कि इसे कर्नेल मेनलाइन में लागू किया गया था। मुझे सिस्टम हेडर फ़ाइलों में उन विकल्पों की परिभाषा नहीं मिल रही है।

संदर्भ के लिए, आप नीचे दिए गए 'netstat --timers' के माध्यम से अपने रखरखाव सॉकेट विकल्प की निगरानी कर सकते हैं। https://stackoverflow.com/questions/34914278

netstat -c --timer | grep "192.0.0.1:43245    192.0.68.1:49742" 

tcp  0  0 192.0.0.1:43245    192.0.68.1:49742   ESTABLISHED keepalive (1.92/0/0) 
tcp  0  0 192.0.0.1:43245    192.0.68.1:49742   ESTABLISHED keepalive (0.71/0/0) 
tcp  0  0 192.0.0.1:43245    192.0.68.1:49742   ESTABLISHED keepalive (9.46/0/1) 
tcp  0  0 192.0.0.1:43245    192.0.68.1:49742   ESTABLISHED keepalive (8.30/0/1) 
tcp  0  0 192.0.0.1:43245    192.0.68.1:49742   ESTABLISHED keepalive (7.14/0/1) 
tcp  0  0 192.0.0.1:43245    192.0.68.1:49742   ESTABLISHED keepalive (5.98/0/1) 
tcp  0  0 192.0.0.1:43245    192.0.68.1:49742   ESTABLISHED keepalive (4.82/0/1) 

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

हाल के कर्नेल संस्करण (2.6.37 के बाद से) में, आप TCP_USER_TIMEOUT विकल्प का उपयोग कर सकते हैं। इस विकल्प का उपयोग एकल सॉकेट के लिए किया जा सकता है।

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