4

async_readとasync_writeを使用するときにtcpクライアントを構造化する正しい方法を理解するのに苦労しています。では、接続後にasync_readを実行し、ハンドラーにasync_writeがあるようです。

私のクライアントとサーバーの場合、クライアントが接続するときに、書き込むメッセージのキューをチェックし、何かを読み取る必要があるかどうかをチェックする必要があります。私が苦労していることの1つは、これが非同期でどのように機能するかを理解することです。

私が想像しているのはasync_connectハンドラーで、sendQueueに何かがある場合、スレッドはasync_writeを呼び出し、async_readを何度も呼び出します。または、async_readを実行する前に、読み取り可能なものがあるかどうかを確認する必要がありますか?以下は私が話していることの例です。

void BoostTCPConnection::connectHandler()
{
    setRunning(true);
    while (isRunning())
    {
        //If send Queue has messages
        if ( sendSize > 0)
        {
            //Calls to async_write
            send();
        }

        boost::shared_ptr<std::vector<char> > sizeBuffer(new std::vector<char>(4));
        boost::asio::async_read(socket_, boost::asio::buffer(data, size), boost::bind(&BoostTCPConnection::handleReceive, shared_from_this(), boost::asio::placeholders::error, sizeBuffer));

   }    
}

void BoostTCPConnection::handleReceive(const boost::system::error_code& error, boost::shared_ptr<std::vector<char> > sizeBuffer)
{

    if (error)
    {
        //Handle Error
        return;
    }

    size_t messageSize(0);
    memcpy((void*)(&messageSize),(void*)sizeBuffer.data(),4);

    boost::shared_ptr<std::vector<char> > message(new std::vector<char>(messageSize) );

    //Will this create a race condition with other reads?
    //Should a regular read happen here
    boost::asio::async_read(socket_, boost::asio::buffer(data, size), 
                    boost::bind(&BoostTCPConnection::handleReceiveMessage, shared_from_this(),
                    boost::asio::placeholders::error, message));

}

void BoostTCPConnection::handleReceiveMessage(const boost::system::error_code& error, boost::shared_ptr<std::vector<char> > rcvBuffer)
{
    if (error)
    {
        //Handle Error
        return;
    }

    boost::shared_ptr<std::string> message(new std::string(rcvBuffer.begin(),rcvBuffer.end())); 
    receivedMsgs_.push_back(message);
}

void BoostTCPConnection::handleWrite(const boost::system::error_code& error,size_t bytes_transferred)
{
    //Success
    if (error.value() == 0) 
        return;
    //else handleError


}
4

1 に答える 1

6

概念的には、async_readデータが受信されるのを待ちます。データが受信され、読み取りがまだ保留されていない後に何かを実行したい場合は、いつでも呼び出す必要があります。同様に、async_writeデータが書き込まれるのを待ちます。データを書き込む必要があり、書き込みがまだ保留されていないときはいつでも呼び出す必要があります。

async_read接続が完了したら呼び出す必要があります。ハンドラーが戻る前に、async_readおそらくもう一度呼び出す必要がありますasync_read

接続に書き込む必要があるasync_write場合は、呼び出す必要があります (書き込みがまだ保留されていない場合)。ハンドラーでさらにasync_write書き込む必要がある場合は、async_write再度呼び出す必要があります。

保留中の読み取りがない場合async_read、書き込みの終了後に読み取りを再開したい場合は、書き込みハンドラーを呼び出すことができます。読み取りを常に保留にしておくこともできます。それはあなた次第です。

を呼び出す前に、読み取るものがあるかどうかを確認しないでくださいasync_read。要点はasync_read、読むものがあるときに完了することです。それまで待って、その間に他のことをする賢い方法です。

于 2012-11-09T19:06:13.390 に答える