Maison >développement back-end >C++ >Comment Boost les écritures asynchrones d'Asio peuvent-elles empêcher l'entrelacement des messages ?

Comment Boost les écritures asynchrones d'Asio peuvent-elles empêcher l'entrelacement des messages ?

DDD
DDDoriginal
2024-12-02 02:53:18586parcourir

How Can Boost Asio's Asynchronous Writes Prevent Message Interleaving?

Écritures asynchrones avec Boost Asio : empêcher l'entrelacement

Énoncé du problème :

Dans une application lorsque plusieurs clients peuvent envoyer des messages de manière asynchrone, il est essentiel d’empêcher l’entrelacement des opérations d’écriture asynchrones. Cela peut entraîner un classement incorrect des messages ou des données tronquées.

Solution :

Une solution simple et efficace à ce problème consiste à implémenter une file d'attente de boîte d'envoi pour chaque client. La file d'attente de la boîte d'envoi sert de tampon pour les messages qui doivent être envoyés.

Comment ça marche :

  1. Mise en file d'attente des messages :Quand un client envoie un message, il est ajouté à la file d'attente de la boîte d'envoi correspondante.
  2. Initiation Écrit : Si la file d'attente de la boîte d'envoi est vide, une opération d'écriture asynchrone est lancée pour envoyer le premier message de la file d'attente.
  3. Gestion de l'achèvement de l'écriture : Une fois l'opération d'écriture terminée, le message correspondant est supprimé de la file d'attente de la boîte d'envoi.
  4. Inspection de la taille de la boîte d'envoi : Le gestionnaire d'achèvement d'écriture asynchrone vérifie si la file d'attente de la boîte d'envoi contient des messages restants. Si tel est le cas, une autre opération d'écriture asynchrone est immédiatement lancée.

Exemple de code :

Vous trouverez ci-dessous un exemple de code simplifié qui démontre l'utilisation d'une file d'attente de boîte d'envoi pour empêcher l'écriture entrelacement :

#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
            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;
};

Avantages :

Cette approche offre plusieurs avantages :

  • Garantit que les opérations d'écriture sont exécutées dans l'ordre dans lequel elles sont reçus.
  • Empêche l'entrelacement des messages provenant de plusieurs clients.
  • Simplifie le code en évitant les mécanismes de synchronisation complexes.

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!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn