2012-07-05 15 views
5

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

public void OnReceive(IAsyncResult result) 
{ 
    try 
    { 
     var bytesReceived = this.Socket.EndReceive(result); 

     if (bytesReceived <= 0) 
     { 
      // normal disconnect 
      return; 
     } 

     // ... 

     this.Socket.BeginReceive...; 
    } 
    catch // SocketException 
    { 
     // abnormal disconnect 
    } 
} 

अब, क्योंकि मैंने पढ़ा है कि यह आसानी से संभव नहीं है, मुझे आश्चर्य है कि मेरी विधि में कुछ गड़बड़ है या नहीं। है? या प्रक्रियाओं को मारने और केबलों और इसी तरह खींचने के बीच कोई अंतर है?

उत्तर

12

यह पूरी तरह से संभव है और ऐसा करने के लिए ठीक है। सामान्य विचार है:

तो EndReceive रिटर्न कुछ भी शून्य के अलावा, आप कार्रवाई करने के लिए आने वाले डेटा की है।

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

यदि EndReceive फेंकता है, तो कनेक्शन की प्रक्रिया असामान्य समाप्ति हुई है (प्रक्रिया मारे गए, नेटवर्क केबल कट, पावर खो गया आदि)।

आप के लिए ध्यान देना होगा अंक की एक जोड़ी:

  1. EndReceive शून्य से भी कम समय कभी वापस नहीं कर सकते हैं (अपने कोड में परीक्षण भ्रामक है)।
  2. यदि यह फेंकता है तो यह SocketException के अलावा अन्य प्रकार के अपवाद को फेंक सकता है।
  3. यदि यह शून्य लौटाता है तो आपको BeginReceive पर कॉल करना बंद करने के लिए सावधान रहना चाहिए; अन्यथा आप BeginReceive और EndReceive के बीच एक अनंत और अर्थहीन पिंग-पोंग गेम शुरू करेंगे (यह आपके CPU उपयोग में दिखाएगा)। आपका कोड पहले से ही ऐसा करता है, इसलिए कुछ भी बदलने की जरूरत नहीं है।
+0

विशेष रूप से +1 क्योंकि मुझे यह पसंद है कि "अगर ऐसा करने के लिए प्रोग्राम किया गया है" तो आप इसे कैसे पसंद करते हैं। –

+2

+1 मैं यह भी इंगित करना चाहूंगा कि आपके पास कभी भी कैच स्टेटमेंट नहीं होना चाहिए जो इसे तब तक पकड़ लेता है जब तक कि इसे फिर से फेंकता न जाए। –

+1

@Alex मैं सभी अपवादों को पकड़ने के निषेध से असहमत हूं जब तक आप उन्हें पुनर्स्थापित नहीं करते। मेरे पास एक टीसीपी-सर्वर क्लास है, जो यहां एक जैसा काम करती है और मैं पूरे सर्वर एप्लिकेशन को समाप्त करने के लिए कुछ यादृच्छिक अपवाद नहीं चाहता हूं। यही कारण है कि मैं सभी अपवादों को पकड़ता हूं और उन्हें ऑनएक्सप्शनकॉट इवेंट-हैंडलर में भेजता हूं, जिसे कुछ लॉगिंग कार्यक्षमता आदि से जोड़ा जाना चाहिए। – Algoman

संबंधित मुद्दे