2012-05-16 14 views
6

मैं बूस्ट एएसओ लाइब्रेरी के साथ एक सर्वर लिख रहा हूं। सर्वर कनेक्शन ऑब्जेक्ट्स (बूस्ट :: एएसओ :: टीसीपी :: सॉकेट के आसपास एक रैपर क्लास) के संग्रह का उपयोग करके कई समवर्ती कनेक्शन को संभालता है। कनेक्शन वर्ग के भीतर, सॉकेट को लगातार socket.async_read_some (...) का उपयोग करने से पढ़ा जा रहा है और जब भी पढ़ने वाले हैंडलर को नए डेटा के साथ बुलाया जाता है, तो socket.async_read_some() को तुरंत पढ़ने के लिए अधिक डेटा के लिए बुलाया जाता है।boost :: asio :: tcp :: सॉकेट बंद करें और बिना हैंडलर को रद्द करें

अब, सर्वर किसी कारण से क्लाइंट को डिस्कनेक्ट करने का निर्णय ले सकता है, इसलिए प्राकृतिक बात करना कनेक्शन.क्लोज़() को कॉल करना है जो बदले में socket.close() को कॉल करता है, जो सभी लंबित एसिंक ऑपरेशन का कारण बनता है रद्द किया जाना यह बूस्ट :: asio :: error :: operation_aborted के साथ बोले जाने वाले पढ़ने वाले हैंडलर (कक्षा कनेक्शन के भीतर एक विधि से जुड़ा हुआ) का कारण बनता है। और मेरी समस्या यह है: मैं नहीं चाहता कि यह हो।

सॉकेट.क्लोज़() के बाद, मैं सॉकेट और कनेक्शन को नष्ट करना चाहता हूं और उसके बाद सर्वर के सक्रिय ग्राहकों की सूची से अपने सूचक को हटा देना चाहता हूं। हालांकि पढ़ने वाले हैंडलर को io_service.run() के अगले पुनरावृत्ति तक नहीं बुलाया जाएगा, जिसका अर्थ है कि मैं सॉकेट या रीड हैंडलर को तुरंत नष्ट नहीं कर सकता, जिसे मैं socket.async_read_some() तक पास कर चुका था जब तक हैंडलर के साथ नहीं बुलाया गया त्रुटि। तो मुझे किसी भी तरह उन वस्तुओं के विनाश में देरी होनी है; यह परेशान करने वाला है।

वहाँ एक सुरक्षित तरीका है करने के लिए या तो

  • async संचालन किसी भी हैंडलर बिना लागू होने के लिए लंबित है, इसलिए मैं सुरक्षित रूप से सॉकेट तुरंत socket.close के बाद() नष्ट कर सकते हैं, या
  • के लिए रद्द करें सुरक्षित रूप से पता है कि जब कोई और हैंडलर संभावित रूप से

या क्या मैं इसे पूरी तरह से गलत तरीके से देख रहा हूं?

उत्तर

4

जब एक async.operation पूर्ण हो जाता है - या तो सफलतापूर्वक या त्रुटि के साथ - इसका पूरा करने वाला हैंडलर लागू होता है। यह महत्वपूर्ण गारंटी है, और मुझे नहीं लगता कि इस व्यवहार को "हैक" करने का प्रयास करना अच्छा विचार है। आपके उपयोग-मामले में आपको जिस समस्या का सामना करना पड़ा है, आमतौर पर shared_ptr (shared_from_this idiom) का उपयोग करके बोल्ड किया जाता है: हैंडलर को shared_ptr<Connection> बांधें, जब आप ऑपरेशन_बॉर्टेड (या कुछ अन्य त्रुटि) प्राप्त करते हैं तो अन्य async_read जारी न करें, ताकि जब सभी हैंडलर हों कनेक्शन किया जाता है कनेक्शन ऑब्जेक्ट को अपनी सॉकेट से नष्ट कर दिया जाता है।

+0

यह बहुत अच्छा लगता है। मुझे यकीन है कि shared_ptr पर्याप्त का उपयोग न करें और enable_shared_from_this के बारे में भी नहीं पता था। मैं ऐसा करता था: "socket.async_connect (एंडपॉइंट, बूस्ट :: बाइंड (और कनेक्शन :: किया गया_कनेक्ट, यह, _1))", तो अब मैं बस एक अतिरिक्त "shared_from_this()" को बाइंड कॉल में जोड़ूंगा और अपडेट करूँगा एक अतिरिक्त shared_ptr के लिए विधि हस्ताक्षर, भले ही वास्तविक shared_ptr को हैंडलर में भी उपयोग नहीं किया जाएगा? अर्थात। ऑब्जेक्ट की गारंटी देने के लिए shared_ptr बस वहां मौजूद है। सही लगता है? – jlh

+0

कम से कम मैंने इसे इस तरह कार्यान्वित किया और यह अब बहुत अच्छा काम करता है। आपका बहुत बहुत धन्यवाद! – jlh

+0

@jlh, यह कहना सही नहीं है कि shared_ptr "हैंडलर में उपयोग नहीं किया जाएगा"। यदि आप shared_ptr पर सदस्य फ़ंक्शन को बाध्य करते हैं, तो यह बाइंडर (बाइंडर() के साथ बनाए गए मज़ेदार) के भीतर संग्रहीत होता है, और फ़ैक्टर आवेषण पर संदर्भित किया जाता है। नतीजतन, जब तक मज़ेदार रहता है तब तक पॉइंटी रहता है। –

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