>백엔드 개발 >C++ >Boost Asio에서 인터리브 `async_write` 호출을 방지하는 방법은 무엇입니까?

Boost Asio에서 인터리브 `async_write` 호출을 방지하는 방법은 무엇입니까?

Linda Hamilton
Linda Hamilton원래의
2024-11-28 01:55:10968검색

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

Boost Asio에서 async_write 호출의 인터리빙을 방지하는 방법

분산 시스템에서는 클라이언트가 서버에 비동기적으로 메시지를 보내는 것이 일반적입니다. 들어오는 메시지를 처리하기 위해 서버는 일반적으로 메시지가 수신된 순서대로 순차적으로 처리되는 대기열 기반 메커니즘을 구현합니다. 그러나 메시지가 인터리브되어 예상치 못한 동작으로 이어질 수 있는 특정 시나리오가 있습니다.

문제 설명

서버가 여러 클라이언트로부터 동시에 메시지를 받는 시나리오를 생각해 보세요. 각 클라이언트의 메시지는 async_write를 사용하여 비동기적으로 처리됩니다. 클라이언트가 빠른 속도로 메시지를 보내는 경우 async_write 호출이 인터리브되어 메시지가 순서대로 처리되지 않을 수 있습니다.

해결책: 대기열 기반 접근 방식

이를 방지하려면 async_write 호출의 인터리빙을 통해 대기열 기반 접근 방식을 사용할 수 있습니다. 작동 방식은 다음과 같습니다.

  1. 각 클라이언트에는 전용 발신 메시지 대기열이 있습니다.
  2. 클라이언트가 메시지를 보내면 해당 메시지가 발신 대기열에 추가됩니다.
  3. 서버는 각 클라이언트에 대해 나가는 대기열의 크기를 확인합니다.
  4. 대기열이 비어 있지 않으면 서버가 시작합니다. async_write 작업을 통해 대기열의 첫 번째 메시지를 보냅니다.
  5. async_write 작업이 완료되면 서버는 대기열을 다시 확인합니다.
  6. 큐에 메시지가 더 있으면 또 다른 async_write 작업 시작됩니다.
  7. 이 프로세스는 대기열의 모든 메시지가 전송될 때까지 반복됩니다.

구현 예

다음 코드 조각은 이 대기열 기반 접근 방식을 구현하는 방법을 보여줍니다.

// 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 );
}

결론

By 대기열 기반 접근 방식을 구현하면 async_write 호출의 인터리브를 효과적으로 방지하여 메시지가 올바른 순서. 이는 메시지 처리 순서가 시스템의 전체 기능에 큰 영향을 미치는 시나리오에서 특히 중요합니다.

위 내용은 Boost Asio에서 인터리브 `async_write` 호출을 방지하는 방법은 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.