2

ステートフルな通信が必要ですが、ブーストのエコー サーバーの例は好きではありません。私のソケットは永遠に読み取る準備ができており、新しいデータを受け取るたびに仮想メソッドを呼び出しますが、いつでもdataAvailable(string)実行できますasync_write

void connected(const boost::system::error_code &ec) {
  _socket.async_read_some(boost::asio::buffer(_buffer, max_length),
      boost::bind(&Session::handler_read, this, boost::asio::placeholders::error,
      boost::asio::placeholders::bytes_transferred));
  //boost::asio::async_read(_socket, boost::asio::buffer(_buffer, max_length),
  //    boost::bind(&Session::handler_read, this, boost::asio::placeholders::error,
  //    boost::asio::placeholders::bytes_transferred));
  std::cout << ">> Session::connected()" << std::endl;
}

void handler_read(const boost::system::error_code &ec, size_t bytes_transferred) {
  if(ec) {
    std::cout << ec.message() << std::endl;
  } else {
    //std::copy(_buffer, _buffer+bytes_transferred, data.begin());
    std::string data(_buffer, _buffer+bytes_transferred);
    std::cout << ">> Session[ " << id() << "]" << "::handler_read(): " <<
            bytes_transferred << " " <<  data << std::endl;
    boost::asio::async_write(_socket, boost::asio::buffer(_buffer, max_length),
            boost::bind(&Session::handler_write, this,
            boost::asio::placeholders::error));
    _socket.async_read_some(boost::asio::buffer(_buffer, max_length),
            boost::bind(&Session::handler_read, this, boost::asio::placeholders::error,
            boost::asio::placeholders::bytes_transferred));
    //boost::asio::async_read(_socket, boost::asio::buffer(_buffer, max_length),
        //    boost::bind(&Session::handler_read, this,
        //    boost::asio::placeholders::error,
        //    boost::asio::placeholders::bytes_transferred));
      //call dataAvailable(_buffer);
  }
}

void handler_write(const boost::system::error_code &ec) {
  if(ec) {
    std::cout << ec.message() << std::endl;
  } else {
    _socket.async_read_some(boost::asio::buffer(_buffer, max_length),
            boost::bind(&Session::handler_read, this, boost::asio::placeholders::error,
            boost::asio::placeholders::bytes_transferred));
    //boost::asio::async_read(_socket, boost::asio::buffer(_buffer, max_length),
        //    boost::bind(&Session::handler_read, this,
        //    boost::asio::placeholders::error,
        //    boost::asio::placeholders::bytes_transferred));
  }
}
  1. この実装は大丈夫ですか?複数のスレッドが読み取りおよび書き込み操作を実行する可能性があるためです。書き込み操作では、マトリックス内のいくつかのセルが更新されます
  2. async_read代わりに使用すると機能しない(受信した文字列をエコーし​​ない)理由async_read_some
  3. 私のリッスン サーバーでは、どこにもlistenメソッドを呼び出していません。それでも機能します。では、なぜリッスン メソッドがあるのでしょうか。そしてそれはいつ使用されますか?
  4. クライアントソケットがクライアント側から終了したときに通知を受け取りたいです。例 クライアントが接続を閉じました。どうすればできますか?私はカミングアウトはEnd Of Fileインを読むread_handlerことですが、それが唯一の方法ですか?
  5. 私は Session クラスを持っており、各セッションには 1 つのソケットがあります。Session*セッションマネージャーにコレクションを保存しています。ソケットを閉じるとdelete、そのセッションがnullになります。の途中で発生する可能性がありvectorます。nullでは、そのセッションを安全に削除する方法は?
4

1 に答える 1

0

コードには重大な問題が 1 つあります。非対称ネットワーク リンクがあり、送信よりもはるかに高速に受信できると想像してください。

  1. メッセージを受信
  2. async_write を実行します (ただし、時間がかかります)
  3. 次の読み取りをスケジュールする
  4. 次のメッセージを受信
  5. 2 番目の async_write を実行します (最初の async_write はまだ完了していません。リンクの反対側でゴミが発生します)。
  6. 次の読み取りをスケジュールする
  7. 最初の async_write が終了し、もう 1 つの async_read_some をスケジュールします

要約すると、同じソケットに対して一度に複数の読み取りと書き込みを行うよう asio に要求します。

async_read_some の代わりに async_read を使用すると機能しない (受信した文字列をエコーし​​ない) 理由

十分なデータ ( ) を送信していますmax_lengthか? 多分あなたは使いたいboost::asio::transfer_at_least(min_length)ですか?

私のリスニングサーバーでは、リッスンメソッドをどこにも呼び出していません。それでも機能します。では、なぜリッスン メソッドがあるのでしょうか。そしてそれはいつ使用されますか?

おそらくどこかにアクセプターオブジェクトを作成します。

クライアントソケットがクライアント側から終了したときに通知を受け取りたいです。例 クライアントが接続を閉じました。どうすればできますか?私の方法は、read_handler で End Of File を読み取ることですが、それが唯一の方法ですか?

EOFクリーンアップを実行するラッパーを作成できます。次に、すべてのカスタム ハンドラーをラッパーでラップし、ラッパーをハンドラーとして boost::asio に渡します。このようにして、必要に応じて EOF エラーを処理する場所が 1 つだけになります。

私は Session クラスを持っており、各セッションには 1 つのソケットがあります。Session* コレクションを Session Manager に保存しています。ソケットを閉じて削除すると、そのセッションがnullになります。ベクトルの途中で発生する可能性があります。では、そのヌル セッションを安全に削除するにはどうすればよいでしょうか。

boost::shared_ptrハンドラーなどで使用しboost::shared_ptrたりboost::weak_ptr、Session Manager のベクトルで使用したりします。

于 2012-06-16T16:29:05.173 に答える