サーバーから可変長メッセージを受け取る必要があるクライアント(Windows 10、Visual C++)にboost :: asioを使用しています。 メッセージは非常に頻繁に(毎秒10メッセージ以上)、各メッセージは約40-100バイトです。私はこのようにasync_read_some
でstreambuf
を使用していWindowsでのboost :: asioでの最適バッファーサイズ
:
void Client::readStart(void)
{
boost::asio::streambuf::mutable_buffers_type buf = _inbox.prepare(std::max((size_t)1024, _socket->available()));
// Start an asynchronous read and call readHandler when it completes or fails
_socket->async_read_some(buf,
boost::bind(&Client::readHandler,
this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
つまり、私は、クライアントがまだあるため、多くのメッセージが蓄積してきたときに大きなバッファを使用する_inbox.prepare(std::max((size_t)1024, _socket->available()))
で動的にバッファサイズを調整しようとしています以前のメッセージを処理します。
_inbox.prepare(262144)
のような大きなバッファを使用することはできません。readHandler
は、より頻繁ではなく、大量のデータで呼び出されるためです。
動的バッファ割り当てを試みても、私は奇妙な遅延とデータの蓄積を経験します。
この
は私のログです:2017-05-09 09:02:25 <debug> Received 1024 bytes
2017-05-09 09:02:25 <debug> Received 372 bytes
2017-05-09 09:02:25 <debug> Received 844 bytes
2017-05-09 09:02:25 <debug> Received 169 bytes
2017-05-09 09:02:25 <debug> Received 1024 bytes
2017-05-09 09:02:25 <debug> Received 379 bytes
2017-05-09 09:02:25 <debug> Received 1385 bytes
2017-05-09 09:02:25 <debug> Received 1421 bytes
2017-05-09 09:02:25 <debug> Received 108 bytes
2017-05-09 09:02:25 <debug> Received 1024 bytes
2017-05-09 09:02:25 <debug> Received 1768 bytes
2017-05-09 09:02:27 <debug> Received 65536 bytes
2017-05-09 09:02:33 <debug> Received 65536 bytes
2017-05-09 09:02:40 <debug> Received 65536 bytes
2017-05-09 09:02:47 <debug> Received 65536 bytes
2017-05-09 09:02:55 <debug> Received 65536 bytes
2017-05-09 09:03:01 <debug> Received 65536 bytes
2017-05-09 09:03:07 <debug> Received 65536 bytes
2017-05-09 09:03:15 <debug> Received 65536 bytes
2017-05-09 09:03:35 <debug> Received 65536 bytes
2017-05-09 09:03:41 <debug> Received 65536 bytes
2017-05-09 09:03:46 <debug> Received 65536 bytes
2017-05-09 09:03:50 <debug> Received 65536 bytes
2017-05-09 09:03:58 <debug> Received 65536 bytes
2017-05-09 09:04:02 <debug> Received 65536 bytes
2017-05-09 09:04:11 <info> Disconnected by remote host
あなたが見ることができるように午前9時02分25秒すべてがOKになるまで、そのデータを蓄積するために開始しreadHandler
が頻繁に呼び出されます(各呼び出しの間に7-8秒)大きなデータ(65536バイト)のチャンクがあります。
最後に、リモートホストは接続を切断します。この切断は、サーバーからクライアント(Wiresharkでトレース)に送信されたTCP ZeroWindowプローブによるものです。つまり、TCPバッファがいっぱいです。
readHandler
が非常に頻繁に呼び出されるのはなぜですか。(クライアントの側では100%CPUの問題ではないと確信しています。クライアントはメッセージとCPUを処理するのが速いです負荷が小さい)。
EDIT:
私はこのコードのソケットにNagleアルゴリズムを無効にしています:
boost::system::error_code error;
_socket->set_option(tcp::no_delay(true), error);
パケットをグループ化するからTCP/IPスタックを防止するための試みで、それはdoesnの助けてください。
EDIT 2:
ボトルネックがどこかに私の処理コードでがあるようですので、私は実際にすぐに十分なデータを受信していないことだし、サーバのネーグルALGOは、以下のR. Joinyで説明した問題を生成。
Wiresharkで送信されたすべてのイーサネットパッケージを識別できますか?おそらく、送信側のネットワークバッファがそれらを1つのイーサネットパッケージにまとめると決めているので、読み込みハンドラはあまり頻繁に呼び出されるのではなく、より多くのデータで呼び出されます。私は確信していませんが、これは通常非常に高い送信レートでしか発生しませんが、これをチェックするには傷つきません –
パスMTU、イーサネットなどのために、1500バイトを超える受信TCPセグメントを決して得られません。 – EJP
@ R.Joiny 65536バイトは単一のイーサネットパケットに入れることはできませんが、EJPは正しいです。他にも問題があるはずです。いずれにしても、Wiresharkトレースをより詳細に分析し、関連するものがあれば質問を更新しようとします。 –