2011-12-11 20 views
15

मैं एएसओ और एसएसएल दोस्तों को बनाने की कोशिश कर रहा हूं। सबकुछ अच्छी तरह से चल रहा है, लेकिन एक बात असुविधा का कारण बन रही है: कैसे पता लगाएं कि सहकर्मी करीबी कनेक्शन है, और स्थिति से अलग करें जब सहकर्मी डेटा भेजने में एक छोटा ब्रेक लेता है, इसे कुछ सेकंड बाद जारी रखने का लक्ष्य रखता है?बूस्ट :: एएसआईओ और एसिंक एसएसएल स्ट्रीम: डेटा/कनेक्शन के अंत का पता लगाने के लिए कैसे?

  • बढ़ावा 1.48
  • OpenSSL 1.0.0e
  • VS10
  • W7 64 पर कार्य का उपयोग कर 32-बिट कोड को संकलित।

मेरा भ्रम इस तथ्य से आता है कि सामान्य सॉकेट और एसएसएल-स्ट्रीम के लिए एएसओ व्यवहार अलग है। यदि मैं टीसीपी :: सॉकेट का उपयोग करता हूं - जब पीयर करीबी कनेक्शन होता है तो मुझे ईओएफ त्रुटि प्राप्त होती है। लेकिन बढ़ावा के लिए :: asio :: ssl :: स्ट्रीम - यह मामला नहीं है। इसके बजाए, async_read_some 0 को बाइट्स के रूप में लौटाता है, और यदि मैं SSL स्ट्रीम से पढ़ना जारी रखने का प्रयास करता हूं - लघु_error (http://www.boost.org/doc/libs/1_47_0/doc/html/boost_asio/overview/core/streams.html) देता है।

तो, प्रश्न यह है: क्या यह व्यवहार की उम्मीद है, या मैं कुछ भी गलत कॉन्फ़िगर करता हूं?

क्लाइंट कोड स्निपेट:।

class client 
{ 
public: 

    // bla-bla-bla-bla-bla .... 
    // 
    void handle_write(const boost::system::error_code& error) 
    { 
     if (!error) 
     { 
      socket_.async_read_some(boost::asio::buffer(reply_, max_length), 
       boost::bind(&client::handle_read, this, 
       boost::asio::placeholders::error, 
       boost::asio::placeholders::bytes_transferred)); 
     } 
     else 
     { 
      std::cout << "Write failed: " << error.message() << "\n"; 
     } 
    } 

    void handle_read(const boost::system::error_code& error, 
        size_t bytes_transferred) 
    { 

     std::cout << "Bytes transfered: " << bytes_transferred << "\n"; 
     if (!error) 
     { 
      std::cout << "Reply: "; 
      std::cout.write(reply_, bytes_transferred); 
      std::cout << "\n"; 

      std::cout << "Reading...\n"; 
      socket_.async_read_some(boost::asio::buffer(reply_, max_length), 
       boost::bind(&client::handle_read, this, 
       boost::asio::placeholders::error, 
       boost::asio::placeholders::bytes_transferred)); 
     } 
     else if (0 != bytes_transferred) 
     { 
      std::cout << "Read failed: " << error.message() << ":" 
        << error.value() << "\n"; 
     } 
    } 

private: 
    boost::asio::ssl::stream<boost::asio::ip::tcp::socket> socket_; 
    boost::asio::streambuf request_; 
    char reply_[max_length]; 
}; 

अगर हम अगर निकाल सकते हैं (! 0 = bytes_transferred), हम "कम पढ़ा" अगर हम कोड का उपयोग करेंगे मिल जाएगा :(

रूप-ऐ

अनुरोध है:

प्राप्त/HTTP/1.0

, उत्पादन कुछ इस तरह हो जाएगा 0

कुकी: नामा-नामा = वाला-वाला

बाइट्स स्थानांतरित: 1024

उत्तर: एचटीटीपी/1.0 200 ठीक सामग्री प्रकार: text/html

..... bla -bla-bla ....

पढ़ना ... बाइट्स स्थानांतरित: 1024

..... bla-bla-bla .... ..... bla-bla-bla ....

पढ़ रहा है ... बाइट्स स्थानांतरित: 482

..... bla-bla-bla ....

पढ़ना ...

बाइट्स स्थानांतरित: 0

इसी समय, बजाय async_read_some अगर हम कोड लिखने, साधारण सॉकेट के लिए क्या EOF वापस आ जाएगी:

boost::asio::async_read(socket_, response_, 
    boost::asio::transfer_at_least(1), 
    boost::bind(&client::handle_read_content, this, 
    boost::asio::placeholders::error)); 
तो एसएसएल-सॉकेट हम आपको के लिए

बाइट्स ट्रांसफर के रूप में 0 प्राप्त करें, और फिर short_read।

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

या, हो सकता है मैं नहीं understant कुछ करना?

WBR, एंड्री

कुछ addentum: SSL/TLS कनेक्शन बंद करने के बारे अन्य पार्टी को सूचित करने के अंकन है। यह अलर्ट को बंद करें। इसके अलावा अंतर्निहित टीसीपी सॉकेट बंद किया जा सकता है।

तो, मूल रूप से, मेरा प्रश्न है: क्यों, उसी स्थिति में (टीसीपी सॉकेट स्पष्ट रूप से बंद कर दिया गया था) मुझे टीसीपी :: सॉकेट के मामले में ईओएफ प्राप्त होता है, और बूस्ट :: asio :: ssl के लिए कुछ भी प्राप्त नहीं होता है: : धारा।

यह बग या asio सुविधा है?

फिर भी एक और योजक: कुछ कारणों से एएसओ ने मुझे ईओएफ नहीं दिया और न ही अगर एसएसएल को क्लोज_नोटिफ़ और न ही अंतर्निहित टीसीपी सॉकेट बंद कर दिया गया।

हाँ, मैं टाइमआउट द्वारा मृत कनेक्शन का पता लगा सकते। लेकिन मैं ठीक से बंद एसएसएल कनेक्शन कैसे पता लगा सकता हूं? शॉर्ट_read प्राप्त करके?

उत्तर

5

आप इन चर्चाओं में रुचि हो सकती है:

अनिवार्य रूप से, तथ्य यह है कि आप एक EOF कभी कभी मिलता है (यहां तक ​​कि ज्यादातर समय) जब दूरस्थ पार्टी एक सादा टीसीपी सॉकेट डिस्कनेक्ट बस भाग्य है। आप सामान्य मामले में इस पर भरोसा नहीं कर सकते हैं, क्योंकि संभवतया निष्क्रिय निष्क्रिय सॉकेट और सॉकेट के बीच इसे अलग किए बिना बंद करने के लिए संभवतः बंद नहीं किया जा सकता है।

आप कुछ सीमांकक जब पढ़ने को रोकने के लिए पता करने के लिए, आवेदन प्रोटोकॉल के स्तर पर, निर्धारित करने होंगे। HTTP में, यह किया जाता है या तो रिक्त पंक्ति है कि हैडर (हेडर के लिए) समाप्त हो जाती है के माध्यम से, Content-Length हैडर कि शरीर की लंबाई, या chunked transfer encoding सीमांकक जब शरीर की लंबाई पहले से ज्ञात नहीं है परिभाषित करता है।

+1

SSL/TLS कनेक्शन बंद करने के बारे अन्य पार्टी को सूचित करने के अंकन है। यह अलर्ट को बंद करें। इसके अलावा अंतर्निहित टीसीपी सॉकेट बंद हो रहा है। तो, मूल रूप से, मेरे सवाल किया गया था: क्यों, एक ही स्थिति में (टीसीपी सॉकेट स्पष्ट रूप से बंद हो गया) मैं टीसीपी :: सॉकेट के मामले में EOF प्राप्त करते हैं, और बढ़ावा :: asio :: ssl :: स्ट्रीम के लिए कुछ भी प्राप्त नहीं होता है । क्या यह बग या सुविधा है? – Amdei

+0

निश्चित रूप से, 'clos_notify' साफ़ क्लोजर के लिए है, जो आपको बुरे लोगों का पता लगाने में मदद नहीं करेगा। मुझे 'boost :: asio :: ssl :: stream' के बारे में बहुत कुछ पता नहीं है, लेकिन मेरा अनुमान है कि आप एसिंक्रोनस ऑपरेशंस कर रहे हैं और एसएसएल/टीएलएस क्लोजर एसिंक्रोनस ऑपरेशंस के साथ समस्याएं पैदा करेगा (देखें" उचित रूप से बंद एसएसएल सॉकेट "लिंक ऊपर)। यह थोड़ा अलग व्यवहार समझा सकता है। किसी भी तरह से, यह वास्तव में कोई फर्क नहीं पड़ता। यह एक बग नहीं होगा जिसे फिक्सिंग की आवश्यकता है, क्योंकि स्ट्रीम/सॉकेट से पढ़ने को रोकने के लिए यह सही तरीका नहीं है। – Bruno

+0

वैसे, मुझे यकीन है कि आप द्वारा क्या मतलब नहीं कर रहा हूँ "* यह close_notify चेतावनी। इसके अलावा अंतर्निहित TCP सॉकेट बंद किया जा रहा। *", लेकिन एक टीएलएस बंद चेतावनी संकेत नहीं यह नहीं है कि अंतर्निहित TCP सॉकेट बंद होना चाहिए। – Bruno

14

SSL_R_SHORT_READ त्रुटि यहाँ की उम्मीद है। जब सर्वर SSL_Shutdown के साथ एक साफ शट डाउन शुरू करता है तो यह क्लाइंट को बंद अधिसूचना शटडाउन अलर्ट भेजता है। Asio कार्यान्वयन इसे की श्रेणी के साथ SSL_R_SHORT_READ त्रुटि में मानचित्र करता है।यह यह पता लगाकर करता है कि क्या पीयर ने SSL_get_shutdown के माध्यम से शट डाउन शुरू किया है।

यह asio/ssl/detail/impl/engine.ipp शीर्षलेख और विशेष रूप से फ़ंक्शन engine::map_error_code(boost::system::error_code&) का निरीक्षण करके देखा जा सकता है।

मेरा मानना ​​है कि ssl कार्यान्वयन को बढ़ावा देने 1.47 पुनः लिखा गया है, तो पहले के संस्करणों अलग-अलग व्यवहार किया है।

+0

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

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