Maison >développement back-end >C++ >Comment empêcher les appels « async_write » entrelacés dans Boost Asio ?
Dans les systèmes distribués, il est courant que les clients envoient des messages aux serveurs de manière asynchrone. Pour gérer les messages entrants, les serveurs implémentent généralement un mécanisme basé sur une file d'attente dans lequel les messages sont traités séquentiellement dans l'ordre dans lequel ils sont reçus. Cependant, il existe certains scénarios dans lesquels les messages peuvent s'entrelacer, entraînant un comportement inattendu.
Considérez un scénario impliquant un serveur qui reçoit des messages de plusieurs clients simultanément. Les messages de chaque client sont traités de manière asynchrone à l'aide de async_write. Si les clients envoient des messages à un rythme rapide, il est possible que les appels async_write soient entrelacés, ce qui entraîne un traitement des messages dans le désordre.
Pour éviter Pour l'entrelacement des appels async_write, une approche basée sur la file d'attente peut être utilisée. Voici comment cela fonctionne :
// Include necessary headers #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 ); }ConclusionEn implémentant une approche basée sur la file d'attente, l'entrelacement des appels async_write peuvent être efficacement évités, en garantissant que les messages sont traités dans le bon ordre. Ceci est particulièrement important dans les scénarios où l'ordre de traitement des messages a un impact significatif sur la fonctionnalité globale du système.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!