दिलचस्प पोस्ट
पायथन के साथ एक ईमेल कैसे भेजें? बुलाहट – हानिकारक माना जाता है बैबल और वेबपैक का उपयोग करते समय मैं स्रोत मेप कैसे उत्पन्न करूं? आईपी ​​पते को कैसे पिंग करें नेविगेशन जेलीबीन पर टूट गया? पायथन में सापेक्ष पथ मैं गिटहब रेपो में फाइलों और फ़ोल्डरों को कैसे जोड़ूं? क्या Google Maps मार्कर को इसके मानचित्र के केन्द्र पर हमेशा तय करने का कोई तरीका है? जावास्क्रिप्ट में हेक्स को दशमलव में कैसे परिवर्तित करना है? नेविगेशन बार की जांच करें "लैंडस्केप" अभिविन्यास मोड को बल दें एडीबी सर्वर पुराना है CTCallCenter का उपयोग करते हुए एक कॉल इवेंट कैसे प्राप्त करें: setCallEventHandler: वह ऐप निलंबित कर दिया गया था? क्रोम की दुर्भावनापूर्ण फ़ाइल चेतावनी के आसपास हो रही है बाह्यरेखा त्रिज्या?

asio async_write को बढ़ावा दें: कैसे async_write कॉल interleaving नहीं?

यहां मेरा क्रियान्वयन है:

  • ग्राहक A क्लाइंट बी के लिए एक संदेश भेजें
  • सर्वर डेटा की सही मात्रा में async_read द्वारा संदेश की प्रक्रिया करता है और क्लाइंट ए से नए डेटा के लिए इंतजार करेगा (क्रम में ग्राहक A को ब्लॉक करने के लिए नहीं)
  • बाद में सर्वर जानकारी को संसाधित करेगा (संभवत: एक mysql क्वेरी) और फिर क्लाइंट बी को async_write साथ संदेश भेज async_write

समस्या यह है, यदि क्लाइंट एक संदेश वास्तव में तेजी से भेजता है, तो async_writes पिछले async_write हैंडलर से पहले async_writes हो जाएगा।

क्या इस समस्या से बचने का एक आसान तरीका है?

1 संपादित करें: यदि क्लाइंट सी ग्राहक A के बाद क्लाइंट बी को संदेश भेजता है, तो उसी समस्या को दिखना चाहिए …

2 संपादित करें: यह काम करेगा? क्योंकि यह ब्लॉक लगता है, मुझे नहीं पता है कि …

  namespace structure { class User { public: User(boost::asio::io_service& io_service, boost::asio::ssl::context& context) : m_socket(io_service, context), m_strand(io_service), is_writing(false) {} ssl_socket& getSocket() { return m_socket; } boost::asio::strand getStrand() { return m_strand; } void push(std::string str) { m_strand.post(boost::bind(&structure::User::strand_push, this, str)); } void strand_push(std::string str) { std::cout << "pushing: " << boost::this_thread::get_id() << std::endl; m_queue.push(str); if (!is_writing) { write(); std::cout << "going to write" << std::endl; } std::cout << "Already writing" << std::endl; } void write() { std::cout << "writing" << std::endl; is_writing = true; std::string str = m_queue.front(); boost::asio::async_write(m_socket, boost::asio::buffer(str.c_str(), str.size()), boost::bind(&structure::User::sent, this) ); } void sent() { std::cout << "sent" << std::endl; m_queue.pop(); if (!m_queue.empty()) { write(); return; } else is_writing = false; std::cout << "done sent" << std::endl; } private: ssl_socket m_socket; boost::asio::strand m_strand; std::queue<std::string> m_queue; bool is_writing; }; } #endif 

Solutions Collecting From Web of "asio async_write को बढ़ावा दें: कैसे async_write कॉल interleaving नहीं?"

क्या इस समस्या से बचने का एक आसान तरीका है?

हां, प्रत्येक ग्राहक के लिए एक आउटगोइंग कतार बनाए रखें। async_write पूर्णता हेन्डलर में कतार आकार का निरीक्षण करें, अगर गैर-शून्य, अन्य async_write ऑपरेशन प्रारंभ करें। यहाँ एक नमूना है

 #include <boost/asio.hpp> #include <boost/bind.hpp> #include <deque> #include <iostream> #include <string> class Connection { public: Connection( boost::asio::io_service& io_service ) : _io_service( io_service ), _strand( _io_service ), _socket( _io_service ), _outbox() { } void write( const std::string& message ) { _strand.post( boost::bind( &Connection::writeImpl, this, message ) ); } private: void writeImpl( const std::string& message ) { _outbox.push_back( message ); if ( _outbox.size() > 1 ) { // outstanding async_write return; } this->write(); } void write() { const std::string& message = _outbox[0]; boost::asio::async_write( _socket, boost::asio::buffer( message.c_str(), message.size() ), _strand.wrap( boost::bind( &Connection::writeHandler, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred ) ) ); } void writeHandler( const boost::system::error_code& error, const size_t bytesTransferred ) { _outbox.pop_front(); if ( error ) { std::cerr << "could not write: " << boost::system::system_error(error).what() << std::endl; return; } if ( !_outbox.empty() ) { // more messages to send this->write(); } } private: typedef std::deque<std::string> Outbox; private: boost::asio::io_service& _io_service; boost::asio::io_service::strand _strand; boost::asio::ip::tcp::socket _socket; Outbox _outbox; }; int main() { boost::asio::io_service io_service; Connection foo( io_service ); } 

कुछ महत्वपूर्ण बिंदुओं

  • boost::asio::io_service::strand Connection::_outbox तक पहुंच की रक्षा Connection::_outbox boost::asio::io_service::strand
  • एक हैंडलर Connection::write() से भेजा जाता है Connection::write() क्योंकि यह सार्वजनिक है

यह मेरे लिए स्पष्ट नहीं था कि आप सभी तरीकों के सार्वजनिक होने के बाद से अपने प्रश्न में उदाहरण में समान प्रथाओं का उपयोग कर रहे थे।