दिलचस्प पोस्ट
सी ++ प्रतिनिधि क्या है? क्या मैं <url-pattern> अंदर <filter-maping> कुछ ठोस यूआरएल को बाहर कर सकता हूं? पायथन और urllib2 के साथ स्रोत इंटरफ़ेस आर सीएमडी बैच के लिए कमांड लाइन तर्क पास करना JQuery $ .getScript () विधि का उपयोग करते हुए एकाधिक जेएस फ़ाइलों को कैसे शामिल करें I अजीब जैक्सन अपवाद जब हाइबरनेट ऑब्जेक्ट serializing किया जा रहा है क्या <b> और <i> टैग कभी भी नापसंद हो जाएंगे? Ggplot2 पौराणिक प्रदर्शन आदेश को नियंत्रित करना सी से जावा के रैंडम जनरेटर का पोर्ट? Git चेकआउट: अद्यतन करने वाले पथ स्विचिंग शाखाओं के साथ असंगत है कम्प्यूटिंग कैमरे 4 समांतर अंकों के आधार पर समरूपता मैट्रिक्स के साथ प्रस्तुत करता है AndroidRuntime त्रुटि: पार्सल: मार्शल मान में असमर्थ समय-सीमा वाले ट्यूप्ले की एक सूची को मर्ज करना, जो समय-सीमाओं को ओवरलैप करते हैं .htaccess में 'हैश' यूआरएल फिर से लिखना जेसन सीरियललाइजेशन से संपत्ति को बाहर कैसे करें

Boost :: asio का उपयोग करते समय मुझे प्रत्येक कनेक्शन की आवश्यकता क्यों है?

मैं बूस्ट की वेबसाइट पर HTTP सर्वर 3 उदाहरण की समीक्षा कर रहा हूं

क्या आप लोग कृपया बता सकते हैं कि मुझे प्रत्येक कनेक्शन की आवश्यकता क्यों है? जैसा कि मैं देख सकता हूं कि हम पठन-इवेंट के हेन्डलर में केवल पढ़ने वाले हैं। इसलिए बुनियादी तौर पर read_some कॉल्स क्रमिक हैं इसलिए किनारे की कोई ज़रूरत नहीं है (और तीसरा पैराग्राफ़ के 2 आइटम एक ही बात कहते हैं) बहु-थ्रेडिंग वातावरण में जोखिम कहाँ है?

वेब के समाधान से एकत्रित समाधान "Boost :: asio का उपयोग करते समय मुझे प्रत्येक कनेक्शन की आवश्यकता क्यों है?"

दस्तावेज़ीकरण सही है। आधा डुप्लेक्स प्रोटोकॉल कार्यान्वयन के साथ, जैसे कि HTTP Server 3 , strand आवश्यक नहीं है कॉल श्रृंखलाओं को निम्नानुसार सचित्र किया जा सकता है:

 void connection::start() { socket.async_receive_from(..., &handle_read); ----. } | .------------------------------------------------' | .-----------------------------------------. VV | void connection::handle_read(...) | { | if (result) | boost::asio::async_write(..., &handle_write); ---|--. else if (!result) | | boost::asio::async_write(..., &handle_write); --|--| else | | socket_.async_read_some(..., &handle_read); ----' | } | .---------------------------------------------------' | V void handle_write(...) 

जैसा कि चित्रण में दिखाया गया है, प्रति पथ केवल एक एकल अतुल्यकालिक घटना शुरू की गई है। socket_ पर हैंडलर या ऑपरेशन के समवर्ती निष्पादन की कोई संभावना नहीं है, यह एक अंतर्निहित किनारा में चल रहा है।


धागा सुरक्षा

हालांकि यह उदाहरण में एक मुद्दा के रूप में खुद को प्रस्तुत नहीं करता है, मैं एक विशेष विवरण के साथ किस्में और boost::asio::async_write संचालन, जैसे boost::asio::async_write । विवरण समझाए जाने से पहले बूस्ट के साथ धागा सुरक्षा मॉडल को पहले आइए। अधिकांश Boost.Asio ऑब्जेक्ट्स के लिए, किसी ऑब्जेक्ट पर लंबित एकाधिक एसिंक्रोनस ऑपरेशन के लिए सुरक्षित है; यह केवल निर्दिष्ट है कि वस्तु पर समवर्ती कॉल असुरक्षित हैं। नीचे के आरेख में, प्रत्येक स्तंभ एक धागा का प्रतिनिधित्व करता है और प्रत्येक पंक्ति का प्रतिनिधित्व करता है कि समय पर एक धागा एक क्षण में क्या कर रहा है।

एक एकल थ्रेड के लिए अनुक्रमिक कॉल बनाने के लिए सुरक्षित है जबकि अन्य धागे कोई भी नहीं बनाते हैं:

  धागा_1 |  thread_2
 -------------------------------------- + ----------- ----------------------------
 socket.async_receive (...);  |  ...
 socket.async_write_some (...);  |  ... 

कॉल करने के लिए कई थ्रेड्स के लिए यह सुरक्षित है, लेकिन समवर्ती नहीं है:

  धागा_1 |  thread_2
 -------------------------------------- + ----------- ----------------------------
 socket.async_receive (...);  |  ...
 ... |  socket.async_write_some (...); 

हालांकि, एकाधिक थ्रेड्स के लिए कॉलों को समवर्ती बनाने के लिए यह सुरक्षित नहीं है 1 :

  धागा_1 |  thread_2
 -------------------------------------- + ----------- ----------------------------
 socket.async_receive (...);  |  socket.async_write_some (...);
 ... |  ... 

किस्में

समवर्ती निमंत्रणों को रोकने के लिए, हैंडलर अक्सर किस्में के भीतर से आते हैं यह या तो द्वारा किया जाता है:

  • strand.wrap साथ हेन्डलर strand.wrap । यह एक नया हेन्डलर वापस करेगा, जो कि किनारा के माध्यम से प्रेषित होगा
  • किनारा के माध्यम से सीधे पोस्टिंग या प्रेषण

प्रबन्ध संचालन शुरू की गई है, जिस किनारे की रचना की गई है, के बजाय एक मौजूद है, अगर हैंडलर की किनारा के भीतर धारा में मध्यवर्ती कॉल के लिए तैयार ऑपरेशन अद्वितीय होते हैं अन्य परिचालनों की तुलना में, यह उस झुकाव को प्रस्तुत करता है जहां किनारा निर्दिष्ट किया जाता है यहां कुछ उदाहरण कोड है जो स्ट्रैंड उपयोग पर ध्यान केंद्रित कर रहे हैं, जो एक सॉकेट प्रदर्शित करेगा जो कि एक गैर-रचित ऑपरेशन के माध्यम से पढ़ा जाता है, और समवर्ती रूप से एक रचित ऑपरेशन के साथ लिखा जाता है।

 void start() { // Start read and write chains. If multiple threads have called run on // the service, then they may be running concurrently. To protect the // socket, use the strand. strand_.post(&read); strand_.post(&write); } // read always needs to be posted through the strand because it invokes a // non-composed operation on the socket. void read() { // async_receive is initiated from within the strand. The handler does // not affect the strand in which async_receive is executed. socket_.async_receive(read_buffer_, &handle_read); } // This is not running within a strand, as read did not wrap it. void handle_read() { // Need to post read into the strand, otherwise the async_receive would // not be safe. strand_.post(&read); } // The entry into the write loop needs to be posted through a strand. // All intermediate handlers and the next iteration of the asynchronous write // loop will be running in a strand due to the handler being wrapped. void write() { // async_write will make one or more calls to socket_.async_write_some. // All intermediate handlers (calls after the first), are executed // within the handler's context (strand_). boost::asio::async_write(socket_, write_buffer_, strand_.wrap(&handle_write)); } // This will be invoked from within the strand, as it was a wrapped // handler in write(). void handle_write() { // handler_write() is invoked within a strand, so write() does not // have to dispatched through the strand. write(); } 

हैंडलर प्रकार का महत्व

इसके अलावा, समस्त संचालन के भीतर, बूस्ट.एएसओओ पूर्णतया हेन्डलर के किनारा के माध्यम से मध्यवर्ती संचालकों को आवंटित करने के लिए तर्क आश्रित लुकअप (एडीएल) का उपयोग करता है । जैसे, यह महत्वपूर्ण है कि पूर्णता वाले हैंडलर का प्रकार उचित asio_handler_invoke() हुक है। यदि टाइप asio_handler_invoke() किसी ऐसे प्रकार के लिए होता है जिसमें उपयुक्त asio_handler_invoke() हुक नहीं होता है, जैसे कि जहां कोई boost::function रिटर्न प्रकार के strand.wrap से strand.wrap , तो मध्यवर्ती संचालकों को किनारा के बाहर निष्पादित किया जाता है, और केवल पूरा हैंडलर किनारा के भीतर निष्पादित होगा। अधिक जानकारी के लिए इस उत्तर को देखें।

निम्नलिखित कोड में, सभी मध्यवर्ती संचालकों और पूर्णता वाले हैंडलर किनारा में निष्पादित होंगे:

 boost::asio::async_write(stream, buffer, strand.wrap(&handle_write)); 

निम्नलिखित कोड में, केवल पूरा हैंडलर किनारा के भीतर निष्पादित होगा मध्यवर्ती संचालकों में से कोई भी किनारा में निष्पादित नहीं होगा:

 boost::function<void()> handler(strand.wrap(&handle_write)); boost::asio::async_write(stream, buffer, handler); 

1. संशोधन इतिहास इस नियम के विसंगति का दस्तावेजीकरण करता है। यदि ओएस द्वारा समर्थित है, तुल्यकालिक पढ़ा, लिखना, स्वीकार्य है, और कनेक्शन कार्रवाई थ्रेड सुरक्षित हैं मैं इसे पूर्णता के लिए यहां शामिल करता हूं, लेकिन सावधानी के साथ इसका उपयोग करने का सुझाव देता हूं।

मेरा मानना ​​है कि यह इसलिए है क्योंकि समन्वित ऑपरेशन async_write async_write एकाधिक सॉकेट :: async_write_some से एसिंक्रोनस से बना है। किनारा उन कार्यों को क्रमबद्ध करने के लिए उपयोगी है एएसआईओ के लेखक क्रिस कोहलॉफ़, 1:17 के आस-पास के बारे में अपने बूस्टकॉन में संक्षेप में इसके बारे में बात करते हैं