2016-12-22 11 views
1

私のネットワーキングを行うにはboost asioを使用していますが、私はsslに切り替えたときにネットワークコードがこれ以上働かないことに気付きました。ここでの問題は、この行のようだ:今まで私はそれを理解し、これは常に(inbound_header_.sizeをお読みくださいboost async_read sslですべてのデータを読み取っていない

boost::asio::async_read(socket_, boost::asio::buffer(inbound_header_), 
     boost::bind(&connection::handle_read_header<Handler>, 
      this, boost::asio::placeholders::error, 
      boost::make_tuple(handler))); 

)ハンドラを呼び出す前にバイト。それはほとんどの時間で動作します。しかし、時には0バイトしか読み込まれず、エラーコード0のハンドラが呼び出されることがあります。私はこのコードをboost asio serializationサンプルからコピーしたので、これがうまくいくはずだと思った。接続:: handle_read_headerでのUbuntu 16.04 アサートにブースト1.61.0でテストサンプルhere は、打ち上げ後の最初の数秒で、ほぼすべての時間をヒットしている最小の作業

+0

[mcve]を提供してください。 (例えば、 'inbound_header_.size()'が '0'、' socket_'に対するスレッドセーフティ要件を満たさない、API契約に違反する下位レベルのドライバなど)が複数ある可能性があります。 –

+0

は開始ポストに1を加えました – ACB

+0

[mcve]は、最小限にして、しばしばゼロから作成し、元の質問に含まれている必要があります。外部リンク、およびそれらに含まれる可能性のある重要な情報は、腐敗する可能性があります。 –

答えて

1

async_read()は、バッファがいっぱいになるかエラーが発生するまで読み取ります。これらの条件のいずれも満たさずに読み取りハンドラが呼び出されている場合、未定義のビヘイビアが呼び出されている可能性があります。

異なるオブジェクト:安全なこの特定のケースでは、コードがboost::asio::ssl:::streamのためのスレッドの安全性の要件に違反します。

共有オブジェクト:安全ではありません。また、アプリケーションは、すべての非同期操作が同じ暗黙のストランド内で実行されることを保証する必要があります。

具体的には、書き込み操作は明示的なストランド(connection::strand_)内で実行されます。しかし、読み出し動作はストランドの外部で行われる。サーバを実行する複数のスレッドが存在するため、プログラムはすべての操作が同じストランド内で実行されることを保証できません。 connection::strand_ストランド内からasync_read操作を実行する明示的に、この問題を解決するには

void connection::async_write(...) 
{ 
    ... 
    // `strand_` protects `message_queue_` and guarantees that writes to 
    // `socket_` are only occurring within the strand. 
    strand_.post([...]() 
    { 
     auto empty = message_queue_.empty(); 
     message_queue_.push([=]() 
     { 
      ... 
      // Intermediate and final handlers are performed within `strand_`. 
      boost::asio::async_write(socket_, ... strand_.wrap([...](...) 
      { 
       ... 
       message_queue_.front()() 
      })); 
     }); 
     if (empty) 
     message_queue_.front()(); 
    }); 
} 

void connection::async_read(...) 
{ 
    // Not performed within `strand_`, violating thread safety. 
    boost::asio::async_read(socket_, ..., 
    // Neither intermediate, final handler, nor subsequent read 
    // operations are performed within `strand_`. 
    [](...) 
    { 
     boost::asio::async_read(socket_, ...); 
    } 
    }); 
} 

。さらに、操作のためのリード・ハンドラは、同様にconnection::strand_内にラップする必要があります。

void connection::async_read(...) 
{ 
    strand_.post([...](...) 
    { 
     // async_read is now performed with the strand. 
     boost::asio::async_read(socket_, ..., 
     // Intermediate and final handlers are performed within the strand. 
     strand_.wrap([](...) 
      { 
      boost::asio::async_read(socket_, ...); 
      }); 
    }); 
} 

鎖内で行われるすべての非同期操作とハンドラは、this答えを見ることを保証する方法の詳細については。

+0

ありがとうございます!私はちょうど私は2つの同時読み込み/書き込みがないことを保証しなければならないと仮定し、その読み書きは同時であることを許可されていません – ACB

関連する問題