2011-09-03 5 views
5

इसलिए मैंने सॉकेट क्लास बनाया है जो एसिंक्रोनस रीड और लिखने के लिए बूस्ट :: एएसओ लाइब्रेरी का उपयोग करता है। यह काम करता है, लेकिन मेरे पास कुछ प्रश्न हैं।बूस्ट :: एएसआई एसिंक्रोनस ऑपरेशंस और संसाधन

यहाँ एक बुनियादी कोड उदाहरण है:

class Socket 
{ 
public: 
    void doRead() 
    { 
     m_sock->async_receive_from(boost::asio::buffer(m_recvBuffer), m_from, boost::bind(&Socket::handleRecv, this, boost::asio::placeholders::error(), boost::asio::placeholders::bytes_transferred())); 
    } 

    void handleRecv(boost::system::error_code e, int bytes) 
    { 
     if (e.value() || !bytes) 
     { 
      handle_error(); 
      return; 
     } 
     //do something with data read 
     do_something(m_recvBuffer); 

     doRead(); //read another packet 
    } 

protected: 
    boost::array<char, 1024> m_recvBuffer; 
    boost::asio::ip::udp::endpoint m_from; 
}; 

ऐसा लगता है कि कार्यक्रम, एक पैकेट पढ़ा जाएगा इसे संभाल, फिर एक और पढ़ने के लिए तैयार करते हैं। सरल। लेकिन अगर मैं थ्रेड पूल स्थापित करता हूं तो क्या होगा? अगली कॉल doRead() पढ़ने के डेटा को संभालने से पहले या बाद में होनी चाहिए? ऐसा लगता है कि अगर इसे do_something() से पहले रखा गया है, तो प्रोग्राम तुरंत एक और पैकेट पढ़ने शुरू कर सकता है, और यदि इसे रखा जाता है, तो थ्रेड को do_something() करता है जो संभवतः कुछ समय ले सकता है। अगर मैं हैंडलिंग से पहले doRead() डालता हूं, तो इसका मतलब यह है कि m_readBuffer में डेटा बदल रहा है, जबकि मैं इसे संभालने में बदल सकता हूं?

इसके अलावा, अगर मैं async_send_to() का उपयोग कर रहा हूं, तो क्या मुझे डेटा को अस्थायी बफर में भेजने की प्रतिलिपि बनाना चाहिए, क्योंकि वास्तविक प्रेषण तब तक नहीं हो सकता जब तक कि डेटा दायरे से बाहर नहीं हो जाता? अर्थात

void send() 
{ 
    char data[] = {1, 2, 3, 4, 5}; 
    m_sock->async_send_to(boost::buffer(&data[0], 5), someEndpoint, someHandler); 
} //"data" gets deallocated, but the write might not have happened yet! 

इसके अतिरिक्त, जब सॉकेट बंद कर दिया है, handleRecv एक त्रुटि दर्शाता है कि उसे बाधित किया गया था के साथ बुलाया जाएगा। अगर मैं

Socket* mySocket = new Socket()... 
... 
mySocket->close(); 
delete mySocket; 

कर यह एक त्रुटि का कारण बन सकता, एक मौका है कि mySockethandleRecv() से पहले हटा दिया जाएगा बुलाया जाता है क्योंकि वहाँ/समाप्त?

+0

+1 एक अच्छे प्रश्न के लिए, लेकिन भविष्य में मैं इसे स्टैक ओवरफ्लो पर अलग-अलग प्रश्नों में विभाजित करने का सुझाव दूंगा। –

उत्तर

2

यहां बहुत सारे प्रश्न हैं, मैं एक समय में उन्हें संबोधित करने की कोशिश करूंगा।

लेकिन अगर मैं थ्रेड पूल स्थापित करता हूं तो क्या होगा?

Boost.Asio के साथ एक थ्रेड पूल का उपयोग करने के पारंपरिक तरीके से io_service::run()from multiple threads आह्वान करने के लिए है। सावधान रहें यह एक आकार का फिट नहीं है-हालांकि सभी जवाब, स्केलेबिलिटी या प्रदर्शन के मुद्दे हो सकते हैं, लेकिन यह पद्धति लागू करने के लिए सबसे आसान है। अधिक जानकारी के साथ Stackoverflow पर कई समान questions हैं।

क्या अगला कॉल करना चाहिए डेटा पढ़ने से पहले या बाद में पढ़ें? ऐसा लगता है कि अगर इसे do_something() से पहले रखा जाता है, तो प्रोग्राम तुरंत एक और पैकेट पढ़ने शुरू कर सकता है, और यदि इसे के बाद रखा जाता है, तो थ्रेड कुछ भी करता है जो कुछ भी करता है, जो संभवतः थोड़ी देर ले सकता है।

यह वास्तव में do_something() पर निर्भर करता है m_recvBuffer के साथ क्या करने की आवश्यकता है। यदि आप do_something()doRead() के साथ समानांतर में io_service::post() का उपयोग करना चाहते हैं तो आपको m_recvBuffer की प्रतिलिपि बनाने की आवश्यकता होगी।

अगर मैं से निपटने से पहले doRead() रखा, कि m_readBuffer में डेटा मतलब है, जबकि मैं इसे से निपटने कर रहा हूँ बदल सकता है?

जैसा कि मैंने पहले उल्लेख किया था, हाँ यह हो सकता है और होगा।

इसके अलावा, अगर मैं async_send_to() उपयोग कर रहा हूँ, मैं डेटा एक अस्थायी बफर में भेजे जाने के लिए कॉपी चाहिए, क्योंकि वास्तविक भेजने तक के बाद डेटा क्षेत्र से बाहर गिर गया है ऐसा नहीं कर सकते हैं?

documentation describes रूप में, यह फोन करने वाले के लिए ऊपर (आप) सुनिश्चित करने के लिए बफर अतुल्यकालिक संचालन की अवधि के लिए दायरे में बनी हुई है। जैसा कि आपको संदेह है, आपका वर्तमान उदाहरण अपरिभाषित व्यवहार का आह्वान करता है क्योंकि data[] गुंजाइश से बाहर हो जाएगा।

इसके अतिरिक्त, जब सॉकेट बंद कर दिया है, handleRecv() एक त्रुटि दर्शाता है कि उसे बाधित किया गया था के साथ बुलाया जाएगा।

आप सॉकेट उपयोग करने के लिए जारी रखना चाहते हैं, cancel()interrupt outstanding को अतुल्यकालिक संचालन का उपयोग करें। अन्यथा, close() काम करेगा। किसी परिदृश्य में बकाया एसिंक्रोनस ऑपरेशंस को पारित त्रुटि boost::asio::error::operation_aborted है।