2008-11-15 13 views
23

क्या लंबित ऑपरेशन को रद्द करने का कोई तरीका है (डिस्कनेक्ट किए बिना) या बूस्ट लाइब्रेरी फ़ंक्शंस के लिए टाइमआउट सेट करें?बूस्ट एएसओ में सॉकेट को अवरुद्ध करने पर टाइमआउट कैसे सेट करें?

आईई। मैं बूस्ट एएसओ में सॉकेट को अवरुद्ध करने पर एक टाइमआउट सेट करना चाहता हूं?

सॉकेट.read_some (boost :: asio :: buffer (pData, maxSize), error_);

उदाहरण: मैं सॉकेट से कुछ पढ़ना चाहता हूं, लेकिन अगर 10 सेकंड बीत चुके हैं तो मैं एक त्रुटि फेंकना चाहता हूं।

उत्तर

8

लिनक्स के तहत के साथ विफल हो जाएगा/बीएसडी सॉकेट पर मैं/हे कार्यों पर टाइमआउट सीधे ऑपरेटिंग सिस्टम द्वारा समर्थित है। विकल्प setsocktopt() के माध्यम से सक्षम किया जा सकता है। मुझे नहीं पता कि boost::asio इसे सेट करने या सॉकेट स्क्रिप्टर को सीधे सेट करने की अनुमति देने के लिए एक तरीका प्रदान करता है - बाद वाला मामला वास्तव में पोर्टेबल नहीं है।

यहाँ पूर्णता की खातिर आदमी पेज से विवरण दिया गया है:

SO_RCVTIMEO और SO_SNDTIMEO

  Specify the receiving or sending timeouts until reporting an 
      error. The argument is a struct timeval. If an input or output 
      function blocks for this period of time, and data has been sent 
      or received, the return value of that function will be the 
      amount of data transferred; if no data has been transferred and 
      the timeout has been reached then -1 is returned with errno set 
      to EAGAIN or EWOULDBLOCK just as if the socket was specified to 
      be non-blocking. If the timeout is set to zero (the default) 
      then the operation will never timeout. Timeouts only have 
      effect for system calls that perform socket I/O (e.g., read(2), 
      recvmsg(2), send(2), sendmsg(2)); timeouts have no effect for 
      select(2), poll(2), epoll_wait(2), etc. 
+1

यह एक अच्छा समाधान होगा, लेकिन उनके पास ऐसे सॉकेट विकल्प नहीं हैं। सॉकेट विकल्प यहां देखें: http://www.boost.org/doc/libs/1_37_0/doc/html/boost_asio/reference.html –

+0

बूस्ट अच्छा है लेकिन सही नहीं है :-) –

+4

लेकिन मैं जो कह सकता हूं उससे, asio's read_some() अभी भी आंतरिक रूप से लूप को हमेशा के लिए जारी रखेगा यदि यह कुछ भी नहीं पढ़ता है, इस प्रकार SO_RCVTIMEO के प्रभाव को रद्द करना आप मूल सॉकेट पर सेट हो सकते हैं। ऐसा लगता है कि socket.native() के साथ चयन() का उपयोग करना अभी भी टाइमआउट करने का सबसे स्पष्ट तरीका होगा। –

9

आप एक async_read कर सकता है और यह भी के लिए टाइमर सेट आपका वांछित समय बाहर। फिर यदि टाइमर आग लगती है, तो अपने सॉकेट ऑब्जेक्ट पर कॉल रद्द करें। अन्यथा यदि आपका पठन होता है, तो आप अपना टाइमर रद्द कर सकते हैं। इसके लिए आपको पाठ्यक्रम की एक io_service ऑब्जेक्ट का उपयोग करने की आवश्यकता है।

संपादित करें: आप के लिए मिले एक कोड का टुकड़ा है कि इस

http://lists.boost.org/Archives/boost/2007/04/120339.php

+1

इस स्निपेट में 'io_service :: reset() 'के लिए एक कॉल है। लेकिन इसके लिए प्रलेखन कहता है, 'रन(), run_one(), poll() या poll_one() फ़ंक्शंस के लिए कोई अधूरा कॉल होने पर यह फ़ंक्शन नहीं कहा जाना चाहिए। – Gabriel

+0

यदि यह कोड एएसआई एसिंक में चलाना है कॉलबैक इवेंट, यानी, 'io_service :: run' द्वारा बुलाए गए कुछ के अंदर, मुझे संदेह है कि आपको अपरिभाषित व्यवहार मिलता है। – Gabriel

6

मैं एक ही सवाल था, और कुछ शोध के बाद, सरल, साफ समाधान मैं के साथ आ सकता है अंतर्निहित मिल गया था मूल सॉकेट, और तब तक चयन करें जब तक डेटा पढ़ने के लिए न हो। चयन एक टाइमआउट पैरामीटर ले जाएगा। बेशक, देशी सॉकेट के साथ काम करना पहले स्थान पर एएसओ का उपयोग करने के बिंदु के खिलाफ जाना शुरू होता है, लेकिन फिर से, यह सबसे साफ तरीका प्रतीत होता है। जहां तक ​​मैं कह सकता हूं, एएसओ सिंक्रोनस उपयोग के लिए इसे करने का एक तरीका प्रदान नहीं करता है। कोड:

 // socket here is: boost::shared_ptr<boost::asio::ip::tcp::socket> a_socket_ptr 

     // Set up a timed select call, so we can handle timeout cases. 

     fd_set fileDescriptorSet; 
     struct timeval timeStruct; 

     // set the timeout to 30 seconds 
     timeStruct.tv_sec = 30; 
     timeStruct.tv_usec = 0; 
     FD_ZERO(&fileDescriptorSet); 

     // We'll need to get the underlying native socket for this select call, in order 
     // to add a simple timeout on the read: 

     int nativeSocket = a_socket_ptr->native(); 

     FD_SET(nativeSocket,&fileDescriptorSet); 

     select(nativeSocket+1,&fileDescriptorSet,NULL,NULL,&timeStruct); 

     if(!FD_ISSET(nativeSocket,&fileDescriptorSet)){ // timeout 

       std::string sMsg("TIMEOUT on read client data. Client IP: "); 

       sMsg.append(a_socket_ptr->remote_endpoint().address().to_string()); 

       throw MyException(sMsg); 
     } 

     // now we know there's something to read, so read 
     boost::system::error_code error; 
     size_t iBytesRead = a_socket_ptr->read_some(boost::asio::buffer(myVector), error); 

     ... 

शायद यह आपकी स्थिति के लिए उपयोगी होगा।

-1

आप सिंक्रोनस कॉल को वायदा में लपेट सकते हैं और इसे टाइमआउट (wait_timeout) के साथ पूरा करने के लिए प्रतीक्षा कर सकते हैं।

http://www.boost.org/doc/libs/1_47_0/doc/html/thread/synchronization.html#thread.synchronization.futures

निश्चित रूप से नहीं एक आकार सभी फिट बैठता है, लेकिन जैसे के लिए अच्छी तरह से काम धीमी कनेक्ट टाइमआउट को बाधित करना।

2

क्या grepsedawk का उल्लेख किया गया है के बाद। टाइमआउट एसीओ डॉको के भीतर सेक्शन के दौरान लंबे समय तक चलने वाले एसिंक्रोनस ऑपरेशंस को रद्द करने का तरीका दिखाते हुए कुछ उदाहरण दिए गए हैं। Boost Asio ExamplesAsync TCP client helped me the most.

मुबारक Asyncing :)

13

जब यह प्रश्न पूछा गया था, मुझे लगता है कि ASIO कैसे पूरा करने के लिए क्या ओ पी की जरूरत पर कोई उदाहरण नहीं था, कि इस तरह के एक अवरुद्ध सॉकेट आपरेशन के रूप में एक अवरुद्ध आपरेशन समयबाह्य करने की है। अब आपको यह दिखाने के लिए उदाहरण मौजूद हैं कि यह कैसे करें। उदाहरण लंबा लगता है, लेकिन ऐसा इसलिए है क्योंकि यह अच्छी तरह से टिप्पणी की है। यह दिखाता है कि 'एक शॉट' प्रकार के मोड में ioservice का उपयोग कैसे करें।

मुझे लगता है कि उदाहरण एक अच्छा समाधान है। यहां अन्य समाधान पोर्टेबिलिटी तोड़ते हैं और ioservice का लाभ नहीं लेते हैं। यदि पोर्टेबिलिटी महत्वपूर्ण नहीं है और ioservice बहुत अधिक पसंद की तरह लगता है - फिर भी - आपको एएसआईओ का उपयोग नहीं करना चाहिए। इससे कोई फर्क नहीं पड़ता कि आपके पास एक आईओएस सेवा बनाई जाएगी (लगभग सभी एएसआईओ कार्यक्षमता इस पर निर्भर करती है, यहां तक ​​कि सिंक सिंक भी करती है) तो इसका लाभ उठाएं।

Timeout a blocking asio tcp operation

Timeout a blocking asio udp operation

ASIO प्रलेखन अद्यतन किया गया है, तो कैसे 'gotchas' ASIO से कुछ करने के लिए उपयोग काबू पाने के लिए पर नया उदाहरण के लिए इसे बाहर की जाँच करें।

+0

विंडोज़ पर, 'io_service.run_one()' async_read पर कम से कम कभी नहीं (कम से कम बूस्ट 1.5 9.0 में), जिसके परिणामस्वरूप 100% सीपीयू उपयोग होता है। – rustyx

+3

उदाहरण लंबे हैं क्योंकि दस्तावेज 3x अनावश्यक है। मुझे नहीं लगता कि "अच्छी टिप्पणी"। – ChristophK

1

मूल प्रश्न के बाद भी वर्षों में, अभी भी एक संतोषजनक उत्तर नहीं है।

मैन्युअल चयन का उपयोग कर एक अच्छा विकल्प

  1. फ़ाइल वर्णनकर्ता संख्या गलत checksum की वजह से 1024 से कम
  2. एफडी नकली तौर पर तैयार के रूप में सूचित किया जा सकता होना चाहिए नहीं है।

कॉल io_service.run_one() भी एक बुरा विचार है क्योंकि वहाँ अन्य async विकल्प हमेशा run() के लिए एक io_service की जरूरत हो सकता है। और टीसीपी क्लाइंट को अवरुद्ध करने के बारे में बूस्ट का दस्तावेज़ समझना मुश्किल है।

तो मेरा समाधान यहां है।

{ 
    Semaphore r_sem; 
    boost::system::error_code r_ec; 
    boost::asio::async_read(s,buffer, 
          [this, &r_ec, &r_sem](const boost::system::error_code& ec_, size_t) { 
           r_ec=ec_; 
           r_sem.notify(); 
          }); 
    if(!r_sem.wait_for(std::chrono::seconds(3))) // wait for 3 seconds 
    { 
     s.cancel(); 
     r_sem.wait(); 
     throw boost::system::system_error(boost::asio::error::try_again); 
    } 
    else if(r_ec) 
     throw boost::system::system_error(r_ec); 
} 

यहाँ Semaphore सिर्फ एक म्युटेक्स और एक condition_variable है: कुंजी विचार इस प्रकार है। अपने सभी सॉकेट कॉल, अपने सभी धागे में EINTR के साथ विफल नहीं चाहेंगे
wait_for द्वारा http://en.cppreference.com/w/cpp/thread/condition_variable/wait_for

पूर्ण कोड लागू किया गया है https://github.com/scinart/cpplib/blob/master/include/asio.hpp
उदाहरण में है https://github.com/scinart/cpplib/blob/master/test/test_SyncBoostIO.cpp

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