1

ブーストasioライブラリを使用してtcpサーバーを実装しています。サーバーでは、asio::async_read_some を使用してデータを取得し、asio::write を使用してデータを書き込みます。サーバーコードはそのようなものです。

std::array<char, kBufferSize> buffer_;
std::string ProcessMessage(const std::string& s) {
   if (s == "msg1") return "resp1";
   if (s == "msg2") return "resp2";
   return "";
}
void HandleRead(const boost::system::error_code& ec, size_t size) {
  std::string message(buffer_.data(), size);
  std::string resp = ProcessMessage(message);
  if (!resp.empty()) {
    asio::write(socket, boost::asio::buffer(message), WriteCallback);
  }
  socket.async_read_some(boost::asio::buffer(buffer_));
}

次に、サーバーをテストするクライアントを作成します。コードは次のようなものです

void MessageCallback(const boost::system::error_code& ec, size_t size) {
   std::cout << string(buffer_.data(), size) << std::endl;
}
//Init socket
asio::write(socket, boost::asio::buffer("msg1"));
socket.read_some(boost::asio::buffer(buffer_), MessageCallback);
// Or async_read
//socket.async_read_some(boost::asio::buffer(buffer_), MessageCallback);
asio::write(socket, boost::asio::buffer("msg1"));
socket.read_some(boost::asio::buffer(buffer_), MessageCallback);
// Or async_read
//socket.async_read_some(boost::asio::buffer(buffer_), MessageCallback);

クライアントを実行すると、コードは 2 番目の read_some で待機し、出力は次のようになりますresp1

最初の read_some を削除すると、出力は にresp1resp2なります。これは、サーバーが正しいことを行ったことを意味します。

最初の read_some EATは 2 番目の応答のようですが、MessageCallback 関数には応答しません。

メッセージ境界とは?の質問を読みました。、この問題が「メッセージ境界」の問題である場合、最初の read_some は tcp ソケットからストリームの一部のみを取得するため、2 番目の read_some は何かを出力するはずです。

どうすればこの問題を解決できますか?

更新: クライアント バッファーのサイズを 4 に変更しようとしました。その出力は次のようになります。

resp
resp

read_some 関数は、ソケットからの読み取りよりも少し多くのことを行うようです。Boost コードを読んで、それが真実であることを確認します。

4

1 に答える 1

2

メンバー関数が意図したasync_read_some()とおりに動作しない可能性が非常に高いため、ドキュメントの備考セクションに特に注意してください

読み取り操作では、要求されたバイト数のすべてが読み取れない場合があります。async_read非同期操作が完了する前に、要求された量のデータが読み取られるようにする必要がある場合は、関数の使用を検討してください。

async_read()無料の機能は、あなたが探している保証を提供することに注意してください

async_read_someこの操作は、ストリームの関数への 0 回以上の呼び出しに関して実装され、合成操作として知られています。プログラムは、この操作が完了するまで、ストリームが他の読み取り操作 ( async_read、ストリームのasync_read_some 関数、または読み取りを実行するその他の合成操作など) を実行しないようにする必要があります。

于 2013-07-18T15:59:32.917 に答える