Rumah >pembangunan bahagian belakang >C++ >Bagaimana untuk Mencegah Panggilan `async_write` Berjalin dalam Boost Asio?

Bagaimana untuk Mencegah Panggilan `async_write` Berjalin dalam Boost Asio?

Linda Hamilton
Linda Hamiltonasal
2024-11-28 01:55:10916semak imbas

How to Prevent Interleaved `async_write` Calls in Boost Asio?

Cara Mencegah Interleaving Panggilan async_write dalam Boost Asio

Dalam sistem yang diedarkan, adalah perkara biasa bagi pelanggan untuk menghantar mesej kepada pelayan secara tidak segerak. Untuk mengendalikan mesej masuk, pelayan biasanya melaksanakan mekanisme berasaskan baris gilir di mana mesej diproses secara berurutan mengikut susunan ia diterima. Walau bagaimanapun, terdapat senario tertentu di mana mesej boleh dijalin, membawa kepada gelagat yang tidak dijangka.

Penerangan Masalah

Pertimbangkan senario yang melibatkan pelayan yang menerima mesej daripada berbilang pelanggan secara serentak. Setiap mesej pelanggan diproses secara tak segerak menggunakan async_write. Jika pelanggan menghantar mesej pada kadar yang pantas, panggilan async_write mungkin menjadi bersilang, mengakibatkan mesej diproses tidak teratur.

Penyelesaian: Pendekatan Berasaskan Baris

Untuk mengelakkan interleaving panggilan async_write, pendekatan berasaskan baris gilir boleh digunakan. Begini caranya:

  1. Setiap pelanggan mempunyai baris gilir mesej keluar yang khusus.
  2. Apabila pelanggan menghantar mesej, ia ditambahkan pada baris gilir keluar.
  3. Pelayan menyemak saiz baris gilir keluar untuk setiap pelanggan.
  4. Jika baris gilir tidak kosong, pelayan memulakan operasi async_write untuk menghantar mesej pertama dalam baris gilir.
  5. Setelah selesai operasi async_write, pelayan menyemak baris gilir sekali lagi.
  6. Jika terdapat lebih banyak mesej dalam baris gilir, async_write lain operasi dimulakan.
  7. Proses ini berulang sehingga semua mesej dalam baris gilir telah dihantar berjaya.

Contoh Pelaksanaan

Coretan kod berikut menunjukkan cara melaksanakan pendekatan berasaskan baris gilir ini:

// 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&amp; io_service
            ) :
        _io_service( io_service ),
        _strand( _io_service ),
        _socket( _io_service ),
        _outbox()
    {

    }

    void write( 
            const std::string&amp; message
            )
    {
        _strand.post(
                boost::bind(
                    &amp;Connection::writeImpl,
                    this,
                    message
                    )
                );
    }

private:
    void writeImpl(
            const std::string&amp; message
            )
    {
        _outbox.push_back( message );
        if ( _outbox.size() > 1 ) {
            // outstanding async_write
            return;
        }

        this->write();
    }

    void write()
    {
        const std::string&amp; message = _outbox[0];
        boost::asio::async_write(
                _socket,
                boost::asio::buffer( message.c_str(), message.size() ),
                _strand.wrap(
                    boost::bind(
                        &amp;Connection::writeHandler,
                        this,
                        boost::asio::placeholders::error,
                        boost::asio::placeholders::bytes_transferred
                        )
                    )
                );
    }

    void writeHandler(
            const boost::system::error_code&amp; 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&amp; _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 );
}

Kesimpulan

Oleh melaksanakan pendekatan berasaskan baris gilir, interleaving panggilan async_write boleh dihalang dengan berkesan, memastikan bahawa mesej diproses dalam susunan yang betul. Ini amat penting dalam senario di mana susunan pemprosesan mesej mempunyai kesan yang ketara ke atas kefungsian keseluruhan sistem.

Atas ialah kandungan terperinci Bagaimana untuk Mencegah Panggilan `async_write` Berjalin dalam Boost Asio?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn