2012-08-06 21 views
9

मैं एक क्लाइंट/सर्वर रिश्ता है कि डेटा समय की एक अनिश्चित राशि के लिए आगे और पीछे धक्का करने के लिए है पर काम कर रहा हूँ में एक सॉकेट डिस्कनेक्ट पता लगाने के लिए।कैसे सी #

समस्या मैं पर काबू पाने के लिए प्रयास कर रहा हूँ

है कि मैं एक डिस्कनेक्ट का पता लगाने के लिए एक रास्ता खोजने के लिए प्रबंधित नहीं कर सकते किया जा रहा है क्लाइंट की तरफ है।

मैं अन्य लोगों के समाधान पर गुजरता के एक जोड़े लिया है, बस पकड़ने आईओ अपवाद से, मतदान के लिए सभी तीन SelectModes पर सॉकेट लेकर। मैंने सॉकेट के 'उपलब्ध' फ़ील्ड पर एक चेक के साथ, एक सर्वेक्षण के संयोजन का उपयोग करने का भी प्रयास किया है।

// Something like this 
Boolean IsConnected() 
{ 
    try 
    { 
     bool part1 = this.Connection.Client.Poll(1000, SelectMode.SelectRead); 
     bool part2 = (this.Connection.Client.Available == 0); 

     if (part1 & part2) 
     { 
      // Never Occurs 
      //connection is closed 
      return false; 
     } 
     return true; 
    } 
    catch(IOException e) 
    { 
     // Never Occurs Either 
    } 
} 

सर्वर साइड पर एक 'खाली' चरित्र लिखने के लिए एक प्रयास (\ 0) ग्राहक के लिए एक आईओ अपवाद बलों और सर्वर का पता लगा सकते है कि ग्राहक डिस्कनेक्ट कर दिया गया (बहुत आसान गिग)।

ग्राहक पक्ष पर, एक ही आपरेशन भी इसका अपवाद नहीं अर्जित करता है।

// Something like this 
Boolean IsConnected() 
{ 
    try 
    { 

     this.WriteHandle.WriteLine("\0"); 
     this.WriteHandle.Flush(); 
     return true; 
    } 
    catch(IOException e) 
    { 
     // Never occurs 
     this.OnClosed("Yo socket sux"); 
     return false; 
    } 
} 

एक समस्या मुझे विश्वास है कि मैं एक सर्वेक्षण के माध्यम से एक डिस्कनेक्ट का पता लगाने में कर रहा हूँ, कि मैं काफी आसानी से एक झूठी एक SelectRead पर, सामना कर सकते हैं, तो अपने सर्वर नहीं अभी तक कुछ भी वापस ग्राहक के लिए के बाद से लिखा है आखिरी जांच ... सुनिश्चित नहीं है कि यहां क्या करना है, मैंने इस पहचान को बनाने के लिए हर विकल्प का पीछा किया है जो मुझे मिल सकता है और मेरे लिए कुछ भी 100% नहीं रहा है, और आखिरकार मेरा लक्ष्य सर्वर (या कनेक्शन का पता लगाने के लिए है)) विफलता, ग्राहक को सूचित करें, पुनः कनेक्ट करने की प्रतीक्षा करें, आदि। इसलिए मुझे यकीन है कि आप कल्पना कर सकते हैं कि यह एक अभिन्न अंग है।

किसी के सुझावों की सराहना करें। समय से पहले धन्यवाद।

संपादित करें: कोई भी इस सवाल को देखने के लिए नीचे दिए गए जवाब को ध्यान देना चाहिए, और उस पर मेरी अंतिम टिप्पणी नहीं। मैंने विस्तार से बताया कि मैंने इस समस्या को कैसे पार किया है, लेकिन अभी तक 'Q & ए' शैली पोस्ट बनाना है।

+0

बस IOExceptions को पकड़ें, और एक रीड टाइमआउट का उपयोग करें। आपको इस अन्य सभी malarkey की जरूरत नहीं है। – EJP

+0

मैंने पहले से ही कोशिश की है (क्योंकि आपने वास्तव में मेरी पोस्ट नहीं पढ़ी है ...) और यह हिट या मिस है। एक दूसरे के बाद एक पठन ऑपरेशन का समय एक आईओ का कारण बनता है, जो एक डिस्कनेक्ट को मजबूर करेगा ... लेकिन अगर मुझे डेटा प्राप्त नहीं हुआ है तो क्या होगा ...? – DigitalJedi805

+0

मैंने आपकी पोस्ट पढ़ी। यह 'हिट एंड मिस' नहीं है, यह स्थानीय रूप से और दूरस्थ रूप से बफरिंग एसिंक्रोनस डेटा के अधीन है। आपको असफल कनेक्शन पर पहले लिखने पर अपवाद नहीं मिलेगा, क्योंकि यह अभी तक नहीं पता चला है: टीसीपी ने पुनः प्रयास प्रयासों के बाद इसे बाद में लिखने पर प्राप्त किया होगा। – EJP

उत्तर

12

एक विकल्प का उपयोग करने के टीसीपी जिंदा पैकेट रखना है। आप उन्हें Socket.IOControl() पर कॉल के साथ चालू करते हैं। ।

Socket socket; //Make a good socket before calling the rest of the code. 
int size = sizeof(UInt32); 
UInt32 on = 1; 
UInt32 keepAliveInterval = 10000; //Send a packet once every 10 seconds. 
UInt32 retryInterval = 1000; //If no response, resend every second. 
byte[] inArray = new byte[size * 3]; 
Array.Copy(BitConverter.GetBytes(on), 0, inArray, 0, size); 
Array.Copy(BitConverter.GetBytes(keepAliveInterval), 0, inArray, size, size); 
Array.Copy(BitConverter.GetBytes(retryInterval), 0, inArray, size * 2, size); 
socket.IOControl(IOControlCode.KeepAliveValues, inArray, null); 

रखें: केवल कष्टप्रद सा ​​है कि यह इनपुट के रूप में एक बाइट सरणी लेता है, तो आप में पारित करने के लिए बाइट्स की एक सरणी के लिए अपने डेटा को परिवर्तित करने के लिए है यहाँ एक 10000ms का उपयोग कर एक उदाहरण रखना एक 1000ms पुन: प्रयास के साथ जिंदा है जीवित पैकेट केवल तभी भेजे जाते हैं जब आप अन्य डेटा नहीं भेज रहे होते हैं, इसलिए हर बार जब आप डेटा भेजते हैं, तो 10000ms टाइमर रीसेट हो जाता है।

+0

बहुत बढ़िया, धन्यवाद जोएल, जैसे ही मैंने अपने देव सिस्टम को मारा, मैं उसे एक स्पिन देना सुनिश्चित कर दूंगा। – DigitalJedi805

+0

हे जोएल, तो मुझे लगता है कि मुझे यहां विचार मिलता है लेकिन अगर मैं गलत हूं तो कृपया मुझे सही करें; IOControl विधि सॉकेट पर 'KeepAlive' पैकेट की समय-समय पर डिलीवरी रखती है। मैंने उपरोक्त कोड को मेरे सॉकेटसेवर.क्लिएंट, और सॉकेट क्लाइंट कन्स्ट्रक्टर दोनों में जोड़ा (शब्द के लिए लगभग शब्द)। मैंने टाइमर को एक सेकेंड तक घटा दिया (क्योंकि यह दोनों तरफ से मेरे 'पढ़ने' पर टाइमआउट है?) लेकिन मेरा StreamReader.ReadLine (बस मुझे यह कहते हुए एहसास हुआ कि यह मेरी रणनीति नहीं होनी चाहिए) कभी भी कोई डेटा नहीं लेता ... मैं यह कहना चाहिए कि मुझे यकीन नहीं है कि हम क्यों डाल रहे हैं जो हम सरणी में डाल रहे हैं; क्या मैं इसे लाइन-टर्मिनेट कर सकता हूं? – DigitalJedi805

+0

असल में बस एक ही चीज़ को StreamReader के साथ चलाने का प्रयास किया। कॉल पढ़ें, और अभी भी किसी भी दिशा में कुछ भी नहीं मिला है। हो सकता है कि मैं अवधारणा को पूरी तरह समझ नहीं पा रहा हूं। – DigitalJedi805