私はいくつかのテストを行った。私の結果に基づいて、OSの実装に依存していることは明らかです。参考までに、私は株式Fedoraカーネルでこれをテストしました:2.6.35.10-74.fc14.x86_64
。
一番下の行は、async_resolve()
あなたがdeadline_timer
を設定せずに逃げることができるかもしれない唯一のケースになりそうだということです。合理的な行動をとるためには、他のすべてのケースで実際に必要です。
async_resolve()
async_resolve()
への呼び出し4つのクエリ離れて5秒になりました。ハンドラは、要求の後、エラーboost::asio::error::host_not_found
で20秒後に呼び出されました。
リゾルバのデフォルト設定は5秒(2回の試行)(resolv.h
)です。そのため、設定されているクエリ数の2倍が送信されているようです。この動作は、options timeout
とoptions attempts
を/etc/resolv.conf
に設定することで変更可能です。いずれの場合も、送信されたクエリの数はattempts
に設定されたものの2倍であり、後でhost_not_found
エラーでハンドラが呼び出されました。
このテストでは、単一の構成済みネームサーバーがブラックホールルーティングされていました。ブラックホールルーティング先とasync_connect()
を呼び出す
async_connect()
〜189秒後にエラーboost::asio::error::timed_out
で呼び出されるハンドラになりました。
スタックは、最初のSYNと5回の再試行を送信しました。最初の再試行は3秒後に行われ、再試行タイムアウトは毎回倍増します(3 + 6 + 12 + 24 + 48 + 96 = 189)。リトライ回数を変更することができる。なければなりません
[再送タイマー] SYN セグメントについて:5のデフォルトは、RFC 1122(4.2.3.5)に適合するように選択される
% sysctl net.ipv4.tcp_syn_retries
net.ipv4.tcp_syn_retries = 5
少なくとも セグメントの再送信を提供するのに十分な大きさに設定してください。 少なくとも3分間。 アプリケーションでは、 の接続を閉じることができます(つまり、開かれた試行をあきらめて) 早く接続できます。
3分= 180秒ですが、RFCでは上限が指定されていません。実装が永遠に再試行するのを止めるものは何もありません。ソケットの送信バッファがフルではなかったよう
async_write()
は限り、このハンドラは、常にすぐに呼ばれていました。
私のテストでは、TCP接続が確立され、1分後にasync_write()
というタイマーが設定されました。先にブラックホール後続のトラフィックへのダウンストリームルータの設定
- :接続が確立したが
async_write()
コールする前にされた分の間に、私は騒乱のすべての種類を試してみました。
- ダウンストリームファイアウォールでセッションをクリアするので、宛先からの偽のRSTで応答します。
- どんなに私が何をしたか
/etc/init.d/network stop
を実行していない私のイーサネット
を抜く、次async_write()
はすぐに成功を報告するために、そのハンドラを呼び出します。ファイアウォールがRSTを偽装された場合には 、接続はすぐに閉じて、私は(すぐにboost::asio::error::connection_reset
を報告する)次オペレーションを実行しようとするまで、私がいることを知る方法がありませんでしたました。それ以外の場合、接続は開いたままになり、最終的に17〜18分後にタイムアウトするまでエラーを報告しません。
async_write()
の最悪の場合は、ホストが再送信中で、送信バッファがいっぱいである場合です。バッファがいっぱいになると、async_write()
は再送がタイムアウトするまでハンドラを呼び出しません。 15の再送へのLinuxデフォルト:
% sysctl net.ipv4.tcp_retries2
net.ipv4.tcp_retries2 = 15
は再送信の間の時間は、それぞれの後に増加する(そのような特定の接続の推定ラウンドトリップ時間などの多くの要因に基づいている)が、2分間でクランプされます。したがって、デフォルトの15回の再送信と最悪の場合の2分間のタイムアウトでは、async_write()
ハンドラが呼び出される上限は30分です。呼び出されると、エラーはboost::asio::error::timed_out
に設定されます。
async_read()
この
は限り接続が確立されると、データが受信されないように、そのハンドラを呼び出すことはありません。私はそれをテストする時間がなかった。
私は自分自身の 'deadline_timer'を作成することにこだわらなければならなかったので、私はそれが不要であるかどうかを見ることに非常に興味があります。 – chrisaycock
+1興味深い質問。答えは主にプラットフォームに依存すると思います。私はあなたがLinuxを気にしていると思いますか? –