2009-12-17 9 views
5

मेरे पास एक सर्वर है जो ग्राहकों से कनेक्शन अनुरोध प्राप्त करता है। यह सर्वर एसिंक्रोनस Socket.BeginReceive और Socket.EndReceive विधि का उपयोग करता है। यह कोड here कोड के समान ही है।सी #: सॉकेट से पहले मैं सॉकेट कैसे समाप्त करूं? बेगिन रिसीव वापस कॉल करता है?

मेरे मामले में, Socket.BeginReceive पर कॉल करने के बाद मुझे एक टाइमआउट की आवश्यकता है जैसे कि क्लाइंट कनेक्शन पर लटकता है लेकिन निश्चित समय के लिए किसी भी डेटा को प्रेषित नहीं करता है, मुझे कनेक्शन को समाप्त करने की आवश्यकता है।

  • मैं इस परिदृश्य में कनेक्शन को समाप्त करने के बारे में कैसे जा सकता हूं?
  • टाइमर कोडिंग का सबसे अच्छा तरीका क्या है?

उत्तर

10

बस सॉकेट की Close() विधि को कॉल करें। इसके बाद कॉलबैक विधि बहुत तेज़ी से चली जाएगी, जब आप EndReceive() विधि को कॉल करते हैं तो आपको ObjectDisposedException मिल जाएगा। उस अपवाद को पकड़ने के लिए तैयार रहें।

शायद आप BeginReceive नामक थ्रेड को अवरुद्ध नहीं करना चाहते हैं, तो आपको टाइमआउट का पता लगाने के लिए System.Threading.Timer या System.Timers.Timer की आवश्यकता होगी। इसके कॉलबैक को Close() पर कॉल करना चाहिए। इस कारणों की अपरिहार्य दौड़-स्थिति से सावधान रहें, टाइमर की कॉलबैक समाप्त हो जाने से पहले टाइमर का कॉलबैक चलाएगा यदि प्रतिक्रिया को माइक्रोसेकंड प्राप्त हुआ था। आप सॉकेट बंद कर देंगे, भले ही आपको अच्छी प्रतिक्रिया मिली हो। BeginReceive() पर अगली कॉल तुरंत विफल हो जाएगी।

+0

क्या आपका मतलब है कि सॉकेट की करीबी विधि के बाद कॉलबैक विधि अभी भी चलती है? – Lopper

+1

यदि कोई BeginReceive() लंबित है: हाँ। यह * हमेशा * को EndReceive() कॉल के साथ जोड़ा जाना चाहिए। आप नहीं कर सकते कॉलबैक से बचें। –

+0

धन्यवाद nobugz! :) – Lopper

0

Socket.BeginReceive पर MSDN लेख के अनुसार यह कहा गया

एक लंबित BeginReceive रद्द करने के लिए बंद विधि कॉल।

+0

और बंद विधि के लिए प्रलेखन के लिए उद्धरण के लिए: "कनेक्शन-उन्मुख प्रोटोकॉल के लिए, यह अनुशंसा की जाती है कि आप बंद विधि को कॉल करने से पहले शटडाउन को कॉल करें। इससे यह सुनिश्चित होता है कि सभी डेटा कनेक्ट किए गए सॉकेट पर भेजे जाने और प्राप्त होने से पहले बन्द है।" –

0

आप कुछ शुरुआती डेटा को अतुल्यकालिक रूप से प्राप्त कर सकते हैं और फिर शेष डेटा के लिए सिंक्रोनस प्राप्त कर सकते हैं और क्लाइंट को डिस्कनेक्ट करने के लिए ReceiveTimeout पर भरोसा कर सकते हैं। आप सॉकेट का उपयोग कर सकते हैं। क्लाइंट को बलपूर्वक डिस्कनेक्ट करने के लिए बंद करें।

लेकिन यदि आप केवल async का उपयोग करना चाहते हैं, तो आप टाइमर का उपयोग कर सकते हैं और उन्हें EndReceive पर रीसेट कर सकते हैं। यदि यह समाप्त हो जाता है तो आप क्लाइंट को बलपूर्वक डिस्कनेक्ट कर सकते हैं।

लेकिन मुझे लगता है कि पहला दृष्टिकोण बेहतर है।

7

मुझे पता है कि यह धागा बहुत पुराना है, लेकिन मुझे अभी भी एक ही समस्या का सामना करना पड़ा और मैं यहां दिए गए उत्तर (या उस मामले से कहीं और) से संतुष्ट नहीं था।

लंबित Socket.BeginReceive को रद्द करने का एक बेहतर समाधान Socket.Shutdown पर कॉल करना और Socket.Close पर कॉल करना है। इस तरह एसिंच हैंडलर को "सामान्य रूप से" उठाया जाता है, और Socket.EndReceive पर कॉल 0 -> बदसूरत अपेक्षित अपवाद फेंकने के बजाय। तुम हमेशा एक

if (Socket.EndReceive() > 0) { 
    //Do something 
} else { 
    //Socket has been shut down (either by you or the other end of the connection) 
    //Now it's "safe" to call Socket.Close 
    Socket.Close(); 
} 

ताकि आप भी मैनुअल रद्द संभालने के लिए अपने asynch-कॉलबैक समायोजित करने की आवश्यकता नहीं है होना चाहिए।

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