Skip to content

Instantly share code, notes, and snippets.

@libitte
Created August 21, 2014 08:12
Show Gist options
  • Select an option

  • Save libitte/9ba8b8ca31973cd4af02 to your computer and use it in GitHub Desktop.

Select an option

Save libitte/9ba8b8ca31973cd4af02 to your computer and use it in GitHub Desktop.
linux で blocking モード -> connect は 180sec で timeout
接続の時にクライアント側が、サーバに対してSYNを送信し、ACKが帰ってきたら接続成功なのですが、このACKが帰ってこない時に、クライアントは、SYNの再送を試みます。
このとき再送は、以下のように5回再送されます。
最初のSYN送信    (0秒経過)
3秒経過してACKが、戻らないとき、SYN(1)を再送します。  (3秒経過)
また、6秒経過してACKが、戻らないとき、SYN(2)を再送します。  (9秒経過)
また、12秒経過してACKが、戻らないとき、SYN(3)を再送します。  (21秒経過)
また、24秒経過してACKが、戻らないとき、SYN(4)を再送します。  (45秒経過)
また、48秒経過してACKが、戻らないとき、SYN(5)を再送します。  (93秒経過)
また、96秒経過してACKが、戻らないとき、ここでタイムアウトが発生します
  (189秒経過)
Linuxでは、この再送がデフォルト(初期設定)で、5回再送となっているので、タイムアウトに189秒かかります。
ACKが戻らない理由としては、以下の場合が考えられます。
ローカルまたはピアのネットワークケーブル断線
途中経路の HUB 故障・ルータ故障
ピアのマシンが故障や停電でダウン
指定した IP アドレスに、そもそもマシンが存在しない
自分で、再接続や、エラー処理を行っている時、この時間を短くしたい事がたまにあります。
この場合、再送回数を減らす事で、対応可能です。
/proc/sys/net/ipv4/tcp_syn_retries の値を変更できます。(デフォルト5回、最大255以下)
0に設定すると、再送が行われません。つまり3秒でタイムアウト
1に設定すると、一回再送が行われます。つまり9秒でタイムアウト
2に設定すると、一回再送が行われます。つまり21秒でタイムアウト
3に設定すると、一回再送が行われます。つまり45秒でタイムアウト
4に設定すると、一回再送が行われます。つまり93秒でタイムアウト
5に設定すると、一回再送が行われます。つまり189秒でタイムアウト
3*2^(N-1)秒の間隔(NはN回目のSYN)を空けてSYNパケットが送信される
上記の対応は、一般的な対象方法です。
しかし、サーバの処理が重すぎて、コネクトに失敗するとき等の、タイムアウトが長すぎる
問題は、回避できません
この問題を回避するには、今のところ2つの方法しかなさそうです。
ノンブロッキングとSELECTを使用して、自分で接続タイムアウト処理を書く。
スレッドのタイムアウト処理を使って回避する。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment